/* $RCSFile: PortalModuleControl.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/UI/WebControls/PortalModuleControl.cs $
 * $log$
 * Revision 65 2011/02/22 01:23:08  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 65 2011/02/22 01:22:18  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 19 2011/01/21 17:51:08  christian.surieux
 *   Recover from Sony move files updated in 11/2010 were not in Source Control
 * Revision 6 2010/08/06 19:56:30  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using System.ComponentModel;
using System.Configuration;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.Caching;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Diagnostics;
using System.Web.Script.Serialization;

using AddonNice.Configuration;
using AddonNice.Configuration.Settings;
using AddonNice.Settings;
using AddonNice.Core;
using AddonNice.UI;
using AddonNice.UI.DataTypes;
using AddonNice.UI.WebControls;
using AddonNice.Helpers;
using AddonNice.Security;
using AddonNice.Diagnostics;
using AddonNice.Design;
using AddonNice.BLL.UserConfig;
using AddonNice.BLL.Utils;

using Telerik.Web.UI;

using Trace2    =   System.Diagnostics.Trace;
using Path2     =   AddonNice.Settings.Path;


namespace AddonNice.UI.WebControls
{

	#region Event management for PortalModulesControls
	
	/// <summary>
	/// Packages Extensions to base settings that should apply to all modules
	/// </summary>
	public class ModuleSettingsCreatedEventArgs : EventArgs
	{
		public ISettingsOwner module;
		public ModuleSettingsDictionary Settings;
		
		public ModuleSettingsCreatedEventArgs(ModuleSettingsDictionary _S,ISettingsOwner md)
		{
			Settings	    =	_S;
			module          =   md;
		}
	}

	public delegate void ModuleSettingsCreatedEventHandler(ModuleSettingsCreatedEventArgs e);

	/// <summary>
	/// Public class to manage PortalModule controls events like UpDate, Edit, Delete, etc.
	/// </summary>
	public class ModuleEventArgs : EventArgs
	{
		public PortalModuleControl senderModule     =   null;
		public EventArgs OrgEvent                   =   null;
		public bool Cancel                          =   false;
		public bool Redirect                        =   false;
		public string RedirectUrl                   =   string.Empty;
		public bool FlushCache                      =   false;
		public object  Value                        =   null;

		public ModuleEventArgs(PortalModuleControl orgModule,EventArgs orgEv) 
		{
			senderModule                            =   orgModule;
			OrgEvent                                =   orgEv;
		}
	}

	public delegate void PortalModuleEventHandler(object sender,ModuleEventArgs e);

	#endregion Event management for PortalModulesControls
	
	#region Global Enum for Layouts

	/// <summary>
	/// Localises ModulesLayout types: 'Default' and 'Alt'
	/// </summary>
	public enum ModuleLayoutOption: int
	{
		Default = 0,
		Alt = 1
	}

	#endregion Global Enum for Layouts

	#region Dev version for each module
	
	public class ModuleDevVersion : IComparable<ModuleDevVersion>
	{
		public int Major;
		public int Minor;
		public string Comment;

		public int CompareTo(ModuleDevVersion o)
		{
			if ( Major == o.Major )
				return Minor-o.Minor;
			return Major-o.Major;
		}
	}

	#endregion Dev version for each module


	/// <summary>
	/// The PortalModuleControl class defines a custom 
	/// base class inherited by all portal modules within the Portal.
	/// The PortalModuleControl class defines portal specific properties that are used by the portal framework
	/// to correctly display portal modules.
	/// </summary>
	public class PortalModuleControl : UserControl, AddonNice.Setup.IInstaller, ISettingsOwner
	{
		public enum UserInAdminRole  {NotTested=0,Yes=1,No=2};

		/// <summary>
		/// Use 'ored', None mean not Ok
		/// </summary>
		[FlagsAttribute]
		public enum VersionType : int { None = 0, CrmV3 = 1, CrmV4 = 2, CrmV5 = 2 }; 

		#region Private field variables

		private ModuleConfiguration  _moduleBaseConfiguration       =   new ModuleConfiguration();

		private int             _canEdit				            =	0;
		private int             _canAdd					            =	0;
		private int             _canView				            =	0;
		private int             _canDelete				            =	0;
		private int             _canProperties			            =	0;
		private int             _portalID				            =	0;
		private int             _ItemID                             =   -1;
		private int             _PageID                             =   -1;

		ModuleSettingsDictionary _settings                          =   null;
		private bool			_cacheable				            =	true;
		private bool			_ReadOnly                           =	false; // default value
		private bool			_supportsBack			            =	false; // default value
		private bool            _supportsArrows			            =	true;
		private bool            _supportsHelp			            =	false;  // default value

		private bool            _AddToToolTipManager                =   true; // Should Module be added to Page ToolTipManager
		protected ModulesLayout _CurrentModulesLayout               =   null;
		
		private ViewControlManager _vcm                             =   null;
		private PlaceHolder		_header					            =	new PlaceHolder();
		private PlaceHolder		_footer					            =	new PlaceHolder();
		private PlaceHolder		_headerPlaceHolder		            =	new PlaceHolder();
		private UserInAdminRole _isUserInAdminRole                  =   UserInAdminRole.NotTested;
		
		// min/max./close buttons 
		private int             _canMin					            =	0; 
		private int             _canClose				            =	0;  

		private PlaceHolder _title                                  =   new PlaceHolder();
		private PlaceHolder _buttons                                =   new PlaceHolder();
		private PlaceHolder _body                                   =   new PlaceHolder();

		protected ISettingsInitializer PortalModuleInitializer      =   null;

		#endregion Private field variables

		#region Common config values instanciated for each object
		
		public string CRMAllUsers		            =   LocalizeHelper.Localize("ALL_USERS", "All Users");
		public string DBAllUser		                =   Config.InternallAllUsersRole;
		public string DBAllUser2		            =   Config.InternallAllUsersRole+";";

		public string CRMAdmin                      =   Config.CRMAdminRole;
		public string DBAdmin                       =   Config.InternalAdminRole;
		public string DBAdmin2                      =   Config.InternalAdminRole+";";
		
		#endregion common config values
		
		#region Toolbox for inherance
		
		// CS 10/9/04 avoid FindControl in designMode
		protected bool IsDesignMode
		{
			get
			{
				return DesignMode;
			}
		}

		/// <summary>
		/// Should Module be added to Page ToolTipManager Default true
		/// </summary>
		protected bool AddToToolTipManager
		{
			get
			{
				return _AddToToolTipManager;
			}
			set
			{
				_AddToToolTipManager = value;
			}
		}
		#endregion

		#region AjaxToolbox

		#region Ajax.Net
		public bool HasScriptManager
		{
			get
			{
				if (Page != null)
				{
					ScriptManager sman = ScriptManager.GetCurrent(Page);
					if (sman != null)
						return true;
				}
				return false;
			}
		}

		public ScriptManager PageScriptManager
		{
			get
			{
				return (Page != null ) ? ScriptManager.GetCurrent(Page):null;
			}
		}

		public bool IsInAsyncPostBack
		{
			get
			{
				if (Page != null)
				{
					ScriptManager sman = ScriptManager.GetCurrent(Page);
					if (sman != null)
						return sman.IsInAsyncPostBack;
				}
				return false;
			}
		}
		#endregion Ajax.Net
		#region RadAjax.Net

		public bool HasAjaxManager
		{
			get
			{
				return (RadAjaxManager.GetCurrent(Page) != null );
			}
		}

		public RadAjaxManager AjaxManager
		{
			get
			{
				return RadAjaxManager.GetCurrent(Page);
			}
		}

		public void AddAjaxSetting(Control ajaxifiedControl,Control updatedControl)
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( 
					string.Format("[V]PortalModuleControl AddAjaxSetting ModuleID: {0}, HasAjaxManager: {1}, ajaxifiedControl: {2}, updatedControl: {3}",
						new object[]{ModuleID,HasAjaxManager,ajaxifiedControl,updatedControl}),ModuleTraceSwitch.Sw.Info);
			if ( !HasAjaxManager )
				return;
			AjaxManager.AjaxSettings.AddAjaxSetting(ajaxifiedControl,updatedControl);
		}

		
		#endregion RadAjax.Net
		#endregion AjaxToolbox

		#region CommandItems
		protected override bool OnBubbleEvent(object source, EventArgs args)
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnBubbleEvent source: {0}, args: {1}",source,args),ModuleTraceSwitch.Sw.Info);
			return base.OnBubbleEvent(source, args);
		}
		#endregion CommandItems

		#region ValidationGroup
		
		public virtual string ValidationGroup
		{
			get
			{
				string validationGroup          =   (string)ViewState["ValidationGroup"];
				if (validationGroup != null)
				{
					return validationGroup;
				}
				return string.Empty;
			}
			set
			{
				ViewState["ValidationGroup"]    =   value;
			}
		}

		internal virtual bool RequiresValidation()
		{
			return Page.GetValidators(ValidationGroup).Count > 0;
		}

		internal virtual bool RequiresValidation(string validationGroup)
		{
			return Page.GetValidators(validationGroup).Count > 0;
		}

		#endregion ValidationGroup
		
		#region EventCallBack
		
		internal PostBackOptions GetPostBackOptions(Control control, string argument, string validationGroup, string postBackUrl)
		{
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl GetPostBackOptions BEG argument: {0}, validationGroup: {1}, postBackUrl: {2}", argument, validationGroup,postBackUrl), ModuleTraceSwitch.Sw.Info);
			PostBackOptions options             =   new PostBackOptions(control, argument);
			options.ClientSubmit                =   true;
			if ( Page != null)
			{
				bool reqVal                     =   RequiresValidation( validationGroup);
				if (ModuleTraceSwitch.Sw.TraceVerbose)
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl GetPostBackOptions RequiresValidation: {0}", reqVal), ModuleTraceSwitch.Sw.Info);
				if ( reqVal )
				{
					options.PerformValidation   =   true;
					options.ValidationGroup     =   validationGroup;
				}
				if (!string.IsNullOrEmpty(postBackUrl))
				{
					options.ActionUrl           =   postBackUrl;
				}
			}
			return options;
		}

		protected virtual string GetPostbackEventReference(string arg)
		{
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl GetPostbackEventReference BEG arg: {0}", arg), ModuleTraceSwitch.Sw.Info);
			string eventReference =     Page.ClientScript.GetPostBackEventReference(GetPostBackOptions(this,arg,ValidationGroup,null));
			eventReference        =     eventReference.Replace("\"", "'");
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl GetPostbackEventReference END eventReference: {0}", eventReference), ModuleTraceSwitch.Sw.Info);
			return eventReference;
		}

		#endregion EventCallBack
		
		#region license

		private AddonNice.Core.AddonNice _Adn;
		/// <summary>
		/// Check for AddonNice license
		/// To override in childs if we need totest another license
		/// </summary>
		protected virtual bool CheckLicense
		{
			get
			{
				if (_Adn == null)
					_Adn = new AddonNice.Core.AddonNice();
				if (_Adn != null)
					return _Adn.License.IsValid;
				return false;
			}
		}

		/// <summary>
		/// Check for AddonNice license demo mode
		/// To override in childs if we need to test another license
		/// </summary>
		public virtual bool IsDemo
		{
			get
			{
				if (_Adn == null)
					_Adn = new AddonNice.Core.AddonNice();
				if (_Adn != null)
					return _Adn.DemoMode;
				return true;
			}
		}
		/// <summary>
		/// Get the extended info string from license
		/// </summary>
		public virtual string DemoInfo
		{
			get
			{
				if (_Adn == null)
					_Adn = new AddonNice.Core.AddonNice();
				if (_Adn != null)
					return _Adn.License.Info;
				return string.Empty;
			}
		}
		
		#endregion license

		#region Standard Buttons: they are controls dedicated to data managed by the control

		List<WebControl> StdButtonList      =   new List<WebControl>();
		/// <summary>
		/// Delete button to delete items in module
		/// </summary>
		private WebControl _StdDeleteButton	=	null;
		protected virtual WebControl StdDeleteButton
		{
			get
			{
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdDeleteButton GET BEG _StdDeleteButton null: {0}",(_StdDeleteButton == null)),ButtonTraceSwitch.Sw.Info);
				if ( _StdDeleteButton != null )
					return _StdDeleteButton;
				if ( IsDesignMode )
					return null;
				object ob	=	FindControl("deleteBtn");
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdDeleteButton GET deleteBtn found : {0}",(ob != null)),ButtonTraceSwitch.Sw.Info);
				if ( ob != null && (ob is WebControl ))
					_StdDeleteButton	=	(WebControl)ob;
				return _StdDeleteButton;
			}
			set
			{
				_StdDeleteButton	=	value;
			}
		}


		/// <summary>
		/// Item Edit button, this button should be dedicated to add/edit items in another window
		/// </summary>
		private WebControl _StdEditButton	=	null;
		protected virtual WebControl StdEditButton
		{
			get
			{
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdEditButton GET BEG _StdEditButton null: {0}",(_StdEditButton == null)),ButtonTraceSwitch.Sw.Info);
				if ( _StdEditButton != null )
					return _StdEditButton;
				if ( IsDesignMode )
					return null;
				object ob	=	FindControl("editBtn");
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdEditButton GET editBtn found : {0}",(ob != null)),ButtonTraceSwitch.Sw.Info);
				if ( ob != null && ( ob is WebControl ) )
					_StdEditButton	=	(WebControl)ob;
				return _StdEditButton;
			}
			set
			{
				_StdEditButton	=	value;
			}
		}


		/// <summary>
		/// Standard Add button to directly add an item in module
		/// </summary>
		private WebControl _StdAddButton	=	null;
		protected virtual WebControl StdAddButton
		{
			get
			{
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdAddButton GET BEG _StdAddButton null: {0}",(_StdAddButton == null)),ButtonTraceSwitch.Sw.Info);
				if ( _StdAddButton != null )
					return _StdAddButton;
				if ( IsDesignMode )
					return null;
				object ob	=	FindControl("addBtn");
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdAddButton GET updateBtn found : {0}",(ob != null)),ButtonTraceSwitch.Sw.Info);
				if ( ob != null && ( ob is WebControl ) )
					_StdAddButton	=	(WebControl)ob;
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdAddButton GET END _StdAddButton null: {0}",(_StdUpdateButton == null)),ButtonTraceSwitch.Sw.Info);
				return _StdAddButton;
			}
			set
			{
				_StdAddButton	=	value;
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdAddButton SET, null: {0}",(_StdAddButton == null)),ModuleTraceSwitch.Sw.Info);
			}
		}

		/// <summary>
		/// Standard update button to update item in module
		/// </summary>
		private WebControl _StdUpdateButton	=	null;
		protected virtual WebControl StdUpdateButton
		{
			get
			{
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdUpdateButton GET BEG _StdUpdateButton null: {0}",(_StdUpdateButton == null)),ButtonTraceSwitch.Sw.Info);
				if ( _StdUpdateButton != null )
					return _StdUpdateButton;
				if ( IsDesignMode )
					return null;
				object ob	=	FindControl("updateBtn");
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdUpdateButton GET updateBtn found : {0}",(ob != null)),ButtonTraceSwitch.Sw.Info);
				if ( ob != null && ( ob is WebControl ) )
					_StdUpdateButton	=	(WebControl)ob;
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdUpdateButton GET END _StdUpdateButton null: {0}",(_StdUpdateButton == null)),ButtonTraceSwitch.Sw.Info);
				return _StdUpdateButton;
			}
			set
			{
				_StdUpdateButton	=	value;
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdUpdateButton SET, null: {0}",(_StdUpdateButton == null)),ModuleTraceSwitch.Sw.Info);
			}
		}

		/// <summary>
		/// Standard search button
		/// </summary>
		private WebControl _StdSearchButton = null;
		protected virtual WebControl StdSearchButton
		{
			get
			{
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdSearchButton GET BEG _StdSearchButton null: {0}",(_StdSearchButton == null)),ButtonTraceSwitch.Sw.Info);
				if (_StdSearchButton != null)
					return _StdSearchButton;
				if (IsDesignMode)
					return null;
				object ob = FindControl("searchBtn");
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdSearchButton GET searchBtn found : {0}",(ob != null)),ButtonTraceSwitch.Sw.Info);
				if (ob != null && (ob is WebControl))
					_StdSearchButton = (WebControl)ob;
				return _StdSearchButton;
			}
			set
			{
				_StdSearchButton = value;
			}
		}
		
		/// <summary>
		/// Standard cancel button
		/// </summary>
		private WebControl _cancelButton	=	null;
		protected virtual WebControl cancelButton
		{
			get
			{
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl cancelButton GET BEG _cancelButton null: {0}",(_cancelButton == null)),ButtonTraceSwitch.Sw.Info);
				if ( _cancelButton != null )
					return _cancelButton;
				if ( IsDesignMode )
					return null;
				object ob	=	FindControl("cancelBtn");
				if ( ButtonTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl cancelButton GET cancelBtn found : {0}",(ob != null)),ButtonTraceSwitch.Sw.Info);
				if ( ob != null && ( ob is WebControl ))
					_cancelButton	= (WebControl)ob;
				return _cancelButton;
			}
			set
			{
				_cancelButton	=	value;
			}
		}


		#endregion
	  
		#region Constructor
		
		/// <summary>
		/// Default contructor
		/// </summary>
		public PortalModuleControl()
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]PortalModuleControl Ctor BEG.",ModuleTraceSwitch.Sw.Info);
			_portalID					                    =	portalSettings.PortalID;
			// Warning this will call the virtual method if defined
			InitPortalModuleControl(_baseSettings);
			// mark all settings to be 'module type settings' and belonging to this module
			SetSettingsTypeAndOwner(false,0);
			// We check if current user is in admin CRM Role
			bool ok1                                =   isUserInAdminRole;
			bool ok                                 =   CheckLicense;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Ctor END AdminUser: {0}, License: {1}, Demo: {2}",
					ok1, ok, IsDemo),ModuleTraceSwitch.Sw.Info);
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]PortalModuleControl Ctor END.",ModuleTraceSwitch.Sw.Info);
		}


		/// <summary>
		/// Mark all not marked base settings (ParentDBId == parentDBIdNotSet ) in this module base settings as belonging to this module
		/// If flag set to true force all settings
		/// </summary>
		protected void SetSettingsTypeAndOwner(bool force,int moduleid2Replace)
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl SetSettingsTypeAndOwner BEG force: {0}, ModuleID: {1}, moduleid2Replace: {2}",
					new object[]{force, ModuleID,moduleid2Replace}),ModuleTraceSwitch.Sw.Info);
			// Mark all settingsitems with type and moduleid
			foreach (KeyValuePair<string,SettingItem> pair in _baseSettings)
			{
				SettingItem st  =   pair.Value;
				st.Type         =   SettingsType.Module;
				if ((ModuleID != 0) &&
					( (st.ParentDBId == StStr.parentDBIdNotSet )  || ( force && st.ParentDBId == moduleid2Replace ))
					)
				{
					st.ParentDBId = ModuleID;
				}
				if ( SettingsTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl SetSettingsTypeAndOwner key: {0}, ParentDBId: {1}",pair.Key,st.ParentDBId),SettingsTraceSwitch.Sw.Info);
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]PortalModuleControl SetSettingsTypeAndOwner END.",ModuleTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Called by Ctors, initialize default settings
		/// Return true if license is Ok
		/// </summary>
		public virtual void InitPortalModuleControl(ModuleSettingsDictionary bSettings)
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]PortalModuleControl InitPortalModuleControl BEG.",ModuleTraceSwitch.Sw.Info);

			PortalModuleInitializer                         =   new PortalModuleControlSI(bSettings,this);
		}

		#endregion

		#region security
		
		/// <summary>
		///  Try to check if current user is in admin role
		/// if CRM is not initialized returns false but allow a next check by keeping untested in _isUserInAdminRole
		/// </summary>
		public bool isUserInAdminRole
		{
			get
			{
				// CSU 3/8/7 to allow conception under VStudio
				if ( DesignMode )
					return true;
				switch (_isUserInAdminRole)
				{
					case UserInAdminRole.No:
						return false;
					case UserInAdminRole.Yes:
						return true;
					default:
						if ( PortalSecurity.Wrapper.isInitialized )
						{
							if ( PortalSecurity.IsUserInRoles(CRMAdmin) )
								_isUserInAdminRole = UserInAdminRole.Yes;
							else
								_isUserInAdminRole = UserInAdminRole.No;
						}
						return (_isUserInAdminRole == UserInAdminRole.Yes);
				}
			}
		}
		#endregion security

		#region language utilities
		public static CultureInfo[] GetLanguageList(bool addInvariantCulture)
		{
			return GetLanguageCultureList().ToUICultureArray(addInvariantCulture);
		}

		/// <summary>
		/// Extracts from portalSettings 'SiteSettingsLangList' allowed languages as a LanguageCollection
		/// </summary>
		public static LanguageCultureCollection GetLanguageCultureList()
		{
			//const string LANGUAGE_DEFAULT = "en-US";

			string strLangList      =   Config.DefaultLanguage;//LANGUAGE_DEFAULT; 

			if (HttpContext.Current != null && HttpContext.Current.Items[StStr.strPortalSettings] != null)
			{
				PortalSettings _portalSettings = (PortalSettings)HttpContext.Current.Items[StStr.strPortalSettings];
				if (_portalSettings.CustomSettings != null && _portalSettings.CustomSettings.ContainsKey(StStr.SiteSettingsLangList) )
					strLangList     =   _portalSettings.CustomSettings[StStr.SiteSettingsLangList].Value;
			}
			LanguageCultureCollection langList;
			try
			{
				TypeConverter tc    =   TypeDescriptor.GetConverter(typeof(LanguageCultureCollection));
				langList            =   (LanguageCultureCollection)tc.ConvertTo(strLangList, typeof(LanguageCultureCollection));
				
			}
			catch (Exception ex)
			{
				if ( ModuleTraceSwitch.Sw.TraceError )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl Failed to load languages, loading defaults, ex : {0}", ex),ModuleTraceSwitch.Sw.Info);
				TypeConverter tc    =   TypeDescriptor.GetConverter(typeof(LanguageCultureCollection));
				langList = (LanguageCultureCollection)tc.ConvertTo(Config.DefaultLanguage, typeof(LanguageCultureCollection));
			}
			return langList;
		}

		#endregion

		#region Module Configuration

		/// <summary>
		/// _baseSettings holds settings information in a dedictionnary of strings/SettingsItems
		/// </summary>
		protected ModuleSettingsDictionary _baseSettings =  new ModuleSettingsDictionary();

		string GetModuleSpecialSetting(string settingKey)
		{
			string val  =   new ModulesDB().GetSingleSettings(ModuleID,settingKey);
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl GetModuleSpecialSetting ModuleID: {0}, val: [{1}]",ModuleID,val),ModuleTraceSwitch.Sw.Info);
			return val;
		}

		public bool UseSettingsFromAnotherModule
		{
			get
			{
				return _moduleBaseConfiguration.ModuleSettingsID != StStr.ModuleIDNotAssigned ;
			}
		}

		/// <summary>
		/// Settings for this module are loaded using this module ID
		/// It allows sharing a module settings for a familly of instancied modules
		/// </summary>
		public virtual int ModuleSettingsID
		{
			get
			{
				return _moduleBaseConfiguration.ModuleSettingsID;
			}
			set
			{
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ModuleSettingsID SET ModuleID: {0}, Value: {1}",ModuleID,value),ModuleTraceSwitch.Sw.Info);
				_moduleBaseConfiguration.ModuleSettingsID = value;
			}
		}

		/// <summary>
		/// To override in child classes which could us setting from other modules
		/// The Guid here allows to filter only module from the specified model
		/// By default we can share settings from same modules familly
		/// </summary>
		public virtual Guid ModuleSettingsFilterGuid
		{
			get
			{
				return GuidID;
			}
		}

		/// <summary>
		/// Used to register the base group dedicated to this module
		/// When several groups inside one module, next groups have to be implemented locally
		/// </summary>
		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual string ExtendedResourcesGroup 
		{
			get
			{
				return string.Empty;
			}
		}


		/// <summary>
		/// Module custom settings: loaded from DB or cache
		/// </summary>
		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public ModuleSettingsDictionary Settings 
		{
			get 
			{
				if (_settings == null) 
				{
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Settings GET _settings null ModuleID: {0}, ModuleSettingsID: {1}",ModuleID,ModuleSettingsID),ModuleTraceSwitch.Sw.Info);
					if ( ModuleID == StStr.ModuleIDNotAssigned )
					{
						string msg  =   "[V]PortalModuleControl Settings GET ModuleID NOT initialized";
						if ( ModuleTraceSwitch.Sw.TraceError )
							Trace2.WriteLine( msg,ModuleTraceSwitch.Sw.Info);
						throw new Exception(msg);
					}
					// To avoid duplicating settings when settings is called from a settingitem handler during load
					if ( _baseSettings.Status == SettingsStatus.Loading )
						return _baseSettings;
					_settings       =   _baseSettings.LoadModuleSettings(ModuleID);
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Settings GET loaded count: {0}",_settings.Count),ModuleTraceSwitch.Sw.Info);
					if (ModuleSettingsID != StStr.ModuleIDNotAssigned && ModuleID != ModuleSettingsID)
					{
						if (ModuleTraceSwitch.Sw.TraceVerbose)
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Settings GET Merging ModuleSettingsID: {0}", ModuleSettingsID), ModuleTraceSwitch.Sw.Info);
						_settings.LoadAndMergeDic(ModuleBaseConfiguration,ADNPage);
					}
				}
				return _settings;
			}
			set // to use only from ModuleSettingDictionary to avoid different elements in page and in module
			{
				if (ModuleTraceSwitch.Sw.TraceVerbose)
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Settings SET _settings null: {0}, count: {1}.",(_settings == null),value.Count), ModuleTraceSwitch.Sw.Info);
				_settings           =   value;
			}
		}

		/// <summary>
		/// Module base settings defined by control creator
		/// </summary>
		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public ModuleSettingsDictionary BaseSettings 
		{
			get 
			{
				return _baseSettings;
			}
		}

		/// <summary>
		/// Override on derivates classes.
		/// Return the path of the add control if available.
		/// </summary>
		public virtual string AddModuleControl
		{
			get
			{
				return string.Empty;
			}
		}

		/// <summary>
		/// Override on derivates classes.
		/// Return the path of the edit control if available.
		/// </summary>
		public virtual string EditModuleControl
		{
			get
			{
				return string.Empty;
			}
		}

		/// <summary>
		/// unique key for module caching
		/// </summary>
		public string ModuleCacheKey
		{
			get
			{
				if (HttpContext.Current != null)
				{	
					// changes to Language behaviour require addition of culture names to cache key
					StringBuilder sb				=	new StringBuilder();
					sb.AppendFormat("adn_{0}_mid{1}[{2}+{3}+{4}]", 
						new object[]{portalSettings.BaseAlias, 
							ModuleID, 
							portalSettings.PortalContentLanguage, 
							portalSettings.PortalUILanguage, 
							portalSettings.PortalDataFormattingCulture});
					return sb.ToString();
				}
			return null;
			}
		}

		/// <summary>
		/// The current ID of the module. Is unique for all portals.
		/// Get from moduleConfiguration (read from DB)
		/// </summary>
		[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public int ModuleID 
		{
			get 
			{
				try
				{
					return _moduleBaseConfiguration.ModuleID;
				}
				catch 
				{
					return -1;
				}
			}
			set 
			{
				_moduleBaseConfiguration.ModuleID = value;
				_settings = null; //force cached settings to be reloaded
			}
		}    

		int _originalModuleID = -1;
		/// <summary>
		/// The ID of the orginal module (will be different to ModuleID when using shortcut module)
		/// </summary>
		[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public int OriginalModuleID 
		{
			get 
			{
				try
				{
					if ( _originalModuleID == -1  )
						return ModuleID;
					else
						return _originalModuleID;
				}
				catch 
				{
					return -1;
				}
			}
			set
			{
				_originalModuleID = value;
			}
		}    

		/// <summary>
		/// Configuration
		/// </summary>
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public ModuleConfiguration ModuleBaseConfiguration 
		{
			get 
			{
				return _moduleBaseConfiguration;
			}
			set 
			{
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ModuleBaseConfiguration SET old ModuleID: {0}, new ModuleID: {1}",ModuleID,value.ModuleID),ModuleTraceSwitch.Sw.Info);
				int oldModuleID             =   ModuleID;
				_moduleBaseConfiguration    =   value;
//                if ( oldModuleID != 0 )
				SetSettingsTypeAndOwner(false,oldModuleID);
			}
		}
		
		/// <summary>
		/// GUID of module (mandatory)
		/// </summary>
		[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual Guid GuidID 
		{
			get
			{
				//1.1.8.1324 - 24/01/2003
				throw new NotImplementedException("You must implement an unique GUID for you module");
			}
		}

		/// <summary>
		/// Version of module : should be fixed by developper, it pilots module updating, TBD Store in DB
		/// </summary>
		[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		protected ModuleDevVersion _PortalModuleVersion  =   new ModuleDevVersion(){Major=1, Minor=0,Comment="First Module Version 01/01/2010"};
		public virtual ModuleDevVersion ModuleVersion
		{
			get
			{
				return _PortalModuleVersion;
			}
		}
		#endregion

		#region Events for standard buttons (opposed to module buttons)

		/// <summary>
		/// The FlushCache event is defined using the event keyword.
		/// The type of FlushCache is EventHandler.
		/// </summary>
		public event PortalModuleEventHandler ADNFlushModuleCache;
		// <summary>
		/// Handles FlushCache event at Module level<br/>
		/// Performs FlushCache actions that are common to all Pages<br/>
		/// Can be overridden
		/// </summary>
		protected virtual void OnADNFlushModuleCache() 
		{
			ModuleEventArgs ev  =   new ModuleEventArgs(this,new EventArgs());
			if ( ADNFlushModuleCache != null) 
				ADNFlushModuleCache(this, ev); //Invokes the delegates
			// remove module output from cache, if it's there
			if (HttpContext.Current != null)
				Context.Cache.Remove(ModuleCacheKey);
		}
		
		public event PortalModuleEventHandler ADNAddInModule;

		/// <summary>
		/// Handles OnADNAddModule event from an StdAdd button inside module <br/>
		/// Performs OnADNAddModule actions that are common to all Modules<br/>
		/// Can be overridden
		/// </summary>
		public virtual void OnADNAddInModule(EventArgs e) 
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNAddInModule BEG ModuleID: {0}, IsDemo: {1}, ValidationGroup: {2}.",ModuleID,IsDemo,ValidationGroup),ModuleTraceSwitch.Sw.Info);
			// no update in demo
			if ( IsDemo )
			{
				OnADNSignalDemo(e);
				return;
			}
			Page.Validate(ValidationGroup);
			if (!Page.IsValid)
			{
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( "[V]PortalModuleControl OnADNAddInModule END IsValid false",ModuleTraceSwitch.Sw.Info);
				return;
			}
			ModuleEventArgs ev  =   new ModuleEventArgs(this,e);
			if ( ADNAddInModule != null ) 
				ADNAddInModule(this, ev); //Invokes the delegates
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNAddInModule ModuleID: {0}, Cancel: {1}, FlushCache: {2}, Redirect: {3}, RedirectUrl: {4}.",
					new object[]{ModuleID,ev.Cancel,ev.FlushCache,ev.Redirect,ev.RedirectUrl}),ModuleTraceSwitch.Sw.Info);
			// add Ok
			if (!ev.Cancel)
			{
				//Flush cache
				if (ev.FlushCache)
					OnADNFlushModuleCache();
				if (ev.Redirect)
				{
					string redirUrl =   ev.RedirectUrl;
					if ( string.IsNullOrEmpty(redirUrl) )
						redirUrl    =   HttpUrlBuilder.BuildUrl(PageID);
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNAddInModule END ModuleID: {0}, redirect Url: {1}.",ModuleID,redirUrl),ModuleTraceSwitch.Sw.Info);
					ADNPage.Redirect(redirUrl,true);
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNAddInModule END ModuleID: {0}, NO redirect.",ModuleID),ModuleTraceSwitch.Sw.Info);
			}
		}

		public event PortalModuleEventHandler ADNUpdateModule;

		/// <summary>
		/// Handles OnADNUpdateModule event from std update button inside module <br/>
		/// Performs OnUpdate actions that are common to all Modules<br/>
		/// Can be overridden
		/// </summary>
		public virtual void OnADNUpdateModule(EventArgs e) 
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNUpdateModule BEG ModuleID: {0}, IsDemo: {1}, ValidationGroup: {2}.",ModuleID,IsDemo,ValidationGroup),ModuleTraceSwitch.Sw.Info);
			// no update in demo
			if ( IsDemo )
			{
				OnADNSignalDemo(e);
				return;
			}
			this.Page.Validate(ValidationGroup);
			if (!Page.IsValid)
			{
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( "[V]PortalModuleControl OnADNUpdateModule END IsValid false",ModuleTraceSwitch.Sw.Info);
				return;
			}
			ModuleEventArgs ev  =   new ModuleEventArgs(this,e);
			if ( ADNUpdateModule != null ) 
				ADNUpdateModule(this, ev); //Invokes the delegates
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNUpdateModule ModuleID: {0}, Cancel: {1}, FlushCache: {2}, Redirect: {3}, RedirectUrl: {4}.",
					new object[]{ModuleID,ev.Cancel,ev.FlushCache,ev.Redirect,ev.RedirectUrl}),ModuleTraceSwitch.Sw.Info);
			// update Ok
			if (!ev.Cancel)
			{
				//Flush cache
				if (ev.FlushCache)
					OnADNFlushModuleCache();
				if (ev.Redirect)
				{
					string redirUrl =   ev.RedirectUrl;
					if ( string.IsNullOrEmpty(redirUrl) )
						redirUrl    =   HttpUrlBuilder.BuildUrl(PageID);
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNUpdateModule END ModuleID: {0}, redirect Url: {1}.",ModuleID,redirUrl),ModuleTraceSwitch.Sw.Info);
					ADNPage.Redirect(redirUrl,true);
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNUpdateModule END ModuleID: {0}, NO redirect.",ModuleID),ModuleTraceSwitch.Sw.Info);
			}
		}

		/// <summary>
		/// For search actions in modules
		/// </summary>
		public event PortalModuleEventHandler ADNSearchModule;

		/// <summary>
		/// Handles OnSearch event at Module level<br/>
		/// Performs OnSearch actions that are common to all modules<br/>
		/// Can be overridden
		/// </summary>
		protected virtual void OnADNSearchModule(EventArgs e)
		{
			ModuleEventArgs ev  =   new ModuleEventArgs(this,e);
			if ( ADNSearchModule != null)
				ADNSearchModule(this, ev); //Invokes the delegates
		}

		public event PortalModuleEventHandler ADNSignalDemo;
		/// <summary>
		/// Used to signal a Demo version when any handler is refused due to demo
		/// </summary>
		protected virtual void OnADNSignalDemo(EventArgs e) 
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNSignalDemo BEG ADNSignalDemo!=null: {0}.",(ADNSignalDemo != null)),ModuleTraceSwitch.Sw.Info);
			if ( ADNSignalDemo != null )
			{
				ModuleEventArgs ev  =   new ModuleEventArgs(this,e);
				ADNSignalDemo(this,ev);
			}
		}

		public event PortalModuleEventHandler ADNDeleteInModule;
		/// <summary>
		/// For delete actions in PortalModules
		/// </summary>
		protected virtual void OnADNDeleteInModule(EventArgs e) 
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNDeleteInModule BEG ADNDeleteInModule!=null: {0}.",(ADNDeleteInModule != null)),ModuleTraceSwitch.Sw.Info);
			if ( ADNDeleteInModule != null )
			{
				ModuleEventArgs ev  =   new ModuleEventArgs(this,e);
				ADNDeleteInModule(this,ev);
			}
		}


		/// <summary>
		/// For edit actions in modules
		/// </summary>
		public event PortalModuleEventHandler ADNEditModuleContent;
		/// <summary>
		/// On Edit to be redefined in childs
		/// </summary>
		protected virtual void OnADNEditModuleContent(EventArgs e) 
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnADNEditModuleContent BEG ADNEditModuleContent!=null: {0}.",(ADNEditModuleContent != null)),ModuleTraceSwitch.Sw.Info);
			if ( ADNEditModuleContent != null )
			{
				ModuleEventArgs ev  =   new ModuleEventArgs(this,e);
				ADNEditModuleContent(this,ev);
			}
		}
		#endregion

		#region Std buttons default handlers
		/*
		 * Depending on button we have 2 kinds of handlers automatically set in OnInit
		 */

		/// <summary>
		/// Std Add Button click
		/// </summary>
		void StdAddButton_Click(Object sender, EventArgs e)
		{
			StdAddButtonClick(sender,e);
		}
		void StdAddImgButton_Click(Object sender, ImageClickEventArgs e)
		{
			StdAddButtonClick(sender,e);
		}
		
		private void StdAddButtonClick(Object sender, EventArgs e)
		{
			OnADNAddInModule(e);
		}
		
		/// <summary>
		/// Update Button click
		/// </summary>
		void StdUpdateButton_Click(Object sender, EventArgs e)
		{
			OnADNUpdateModule(e);
		}
		void StdUpdateImgButton_Click(Object sender, ImageClickEventArgs e)
		{
			OnADNUpdateModule(e);
		}
		
		
		void StdSearchButton_Click(Object sender, EventArgs e)
		{
			OnADNSearchModule(e);
		}
		void StdSearchImgButton_Click(Object sender, ImageClickEventArgs e)
		{
			OnADNSearchModule(e);
		}

		void StdEditButton_Click(Object sender, EventArgs e) 
		{
			OnADNEditModuleContent(e);
		}
		
		void StdEditImgButton_Click(Object sender, ImageClickEventArgs e) 
		{
			OnADNEditModuleContent(e);
		}
		
		void StdDeleteImgButton_Click(Object sender, ImageClickEventArgs e) 
		{
			bool idm    =   IsDemo;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdDeleteImgButton_Click BEG IsDemo: {0}",idm),ModuleTraceSwitch.Sw.Info);
			// If not in demo mode we delete
			if (!idm)
				OnADNDeleteInModule(e);
			else OnADNSignalDemo(e);
		}
		
		void StdDeleteButton_Click(Object sender, EventArgs e) 
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]PortalModuleControl StdDeleteButton_Click BEG.",ModuleTraceSwitch.Sw.Info);
			bool idm    =   IsDemo;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl StdDeleteButton_Click IsDemo: {0}",idm),ModuleTraceSwitch.Sw.Info);
			// If not in demo mode we delete
			if (!idm)
				OnADNDeleteInModule(e);
			else OnADNSignalDemo(e);
		}

		#endregion Std buttons default handlers

		#region std messages

		public virtual string StdDeleteMsg
		{
			get
			{
				return LocalizeHelper.Localize("CONFIRM_DELETE","Confirm Delete");
			}
		}
		public virtual string StdDeleteTitle
		{
			get
			{
				return LocalizeHelper.Localize("DELETE", "Delete");
			}
		}
		#endregion std messages

		#region UserControl handlers override

		protected override void OnLoad(EventArgs e)
		{
			bool ModulConfIsNull =   ( ModuleBaseConfiguration == null );
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnLoad BEG PageID: {0}, ModuleID: {1}, ModulConfIsNull: {2}",PageID, ModuleID,ModulConfIsNull),ModuleTraceSwitch.Sw.Info);
			#region set cacheable in ModuleBaseConfiguration
			
			if ( !ModulConfIsNull )
			{
				if ( Cacheable )
					ModuleBaseConfiguration.Cacheable = true; 
				else
					ModuleBaseConfiguration.Cacheable = false;
			}

			#endregion
			
			#region check for window management
			// does this configuration support window mgmt controls?
			if ( Config.SupportWindowMgmt &&  SupportCollapsable )
				_vcm = new ViewControlManager(PageID,ModuleID,HttpContext.Current.Request.RawUrl);
			
			#endregion
			
			// We must add confirm logic
			if (_StdDeleteButton != null && _StdDeleteButton.Visible )
			{
				string msg                  =   StdDeleteMsg;
				string title                =   StdDeleteTitle;
				ADNPage.setClientConfirmAttributes(_StdDeleteButton,msg,title);
			}
			// ToolTipiFy controls
			if ( ADNPage.HasToolTipManager )
			{
				// Module buttons
				foreach (Control ctl in ButtonList)
				{
					if ( ctl.Visible && !string.IsNullOrEmpty(ctl.ClientID) )
						ADNPage.AddToolTipTarget(ctl.ClientID, true,TootipPos.Top);
				}
				//Std buttons
				foreach (WebControl iButton in StdButtonList)
				{
					if( !string.IsNullOrEmpty(iButton.ClientID) )
						ADNPage.AddToolTipTarget(iButton.ClientID, true,TootipPos.Bottom); // we suppose they are placed near page bottom
				}
				AddTargetToGlobalToolTipManager();
			}
			// Then call inherited member which will call modules loaders
			base.OnLoad(e);
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnLoad END PageID: {0}, ModuleID: {1}", PageID, ModuleID),ModuleTraceSwitch.Sw.Info);
		}

		
		/// <summary>
		/// Checks std buttons presence: StdDeleteButton, StdEditButton, StdUpdateButton, StdSearchButton,
		/// Assign handlers
		/// Build Control Hierarchy
		/// </summary>
		protected override void OnInit(System.EventArgs e)
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnInit BEG Module: {0}",ModuleBaseConfiguration.ModuleTitle),ModuleTraceSwitch.Sw.Info);
			// Reserve first place for our layout
			_headerPlaceHolder.Controls.Clear();
			_header.Controls.Clear();
			_footer.Controls.Clear();
			Controls.AddAt(0,_headerPlaceHolder);
			if (!ReadOnly)
			{
				string btnText                              =   string.Empty;
				WebControl iButton                          =   StdDeleteButton;
				if (iButton != null)
				{
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnInit StdDeleteButton found IsDeletable: {0}",IsDeletable), ModuleTraceSwitch.Sw.Info);
					btnText                                 =   LocalizeHelper.Localize("DELETE","Delete");
					iButton.ToolTip                         =   btnText;
					// Assign current permissions to Delete button
					if (!IsDeletable)
					{
						iButton.Visible                     =   false;
					}
					else
					{
						iButton.Visible                     =   true;
						if (iButton is LinkButton)
						{
							LinkButton Button2              =   (LinkButton)StdDeleteButton;
							Button2.Click                   +=  new System.EventHandler(StdDeleteButton_Click);
							Button2.Text                    =   btnText;
							if (ModuleTraceSwitch.Sw.TraceVerbose)
								Trace2.WriteLine("[V]PortalModuleControl OnInit StdDeleteButton StdDeleteButton_Click set for LinkButton.", ModuleTraceSwitch.Sw.Info);
						}
						else if (iButton is ImageButton)
						{
							((ImageButton)iButton).Click    +=      new ImageClickEventHandler(StdDeleteImgButton_Click);
							((ImageButton)iButton).AlternateText =  btnText;
							if (ModuleTraceSwitch.Sw.TraceVerbose)
								Trace2.WriteLine("[V]PortalModuleControl OnInit StdDeleteButton StdDeleteImgButton_Click set for imageButton.", ModuleTraceSwitch.Sw.Info);
						}
						else if (iButton is Button)
						{
							((Button)iButton).Click         +=  new EventHandler(StdDeleteButton_Click);
							if ( string.IsNullOrEmpty(((Button)iButton).Text))
								((Button)iButton).Text      =   btnText;
							if (ModuleTraceSwitch.Sw.TraceVerbose)
								Trace2.WriteLine("[V]PortalModuleControl OnInit StdDeleteButton StdDeleteButton_Click set for button.", ModuleTraceSwitch.Sw.Info);
						}
						iButton.EnableViewState             =   false;
						StdButtonList.Add(iButton);
					}
				}
				iButton                                     =   StdEditButton;
				if (iButton != null)
				{
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnInit StdEditButton found IsEditable: {0}",IsEditable), ModuleTraceSwitch.Sw.Info);
					btnText                                 =   LocalizeHelper.Localize("EDIT","Edit");
					iButton.ToolTip                         =   btnText;
					// Assign current permissions to Edit button
					if (!IsEditable)
					{
						iButton.Visible                     =   false;
					}
					else
					{
						iButton.Visible                     =   true;
						if (iButton is LinkButton)
						{
							LinkButton Button2              =   (LinkButton)StdEditButton;
							Button2.Click                   +=  new System.EventHandler(StdEditButton_Click);
							Button2.Text                    =   btnText;
						}
						else if (iButton is ImageButton)
						{
							((ImageButton)iButton).Click    +=  new ImageClickEventHandler(StdEditImgButton_Click);
							((ImageButton)iButton).AlternateText =  btnText;
						}
						else if (iButton is Button)
						{
							((Button)iButton).Click         +=  new EventHandler(StdEditButton_Click);
							if ( string.IsNullOrEmpty(((Button)iButton).Text))
								((Button)iButton).Text      =   btnText;
						}
						iButton.EnableViewState = false;
						StdButtonList.Add(iButton);
					}
				}
				iButton                                     =   StdAddButton;
				if (iButton != null)
				{
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnInit StdAddButton found IsAddable: {0}",IsAddable), ModuleTraceSwitch.Sw.Info);
					btnText                                 =   LocalizeHelper.Localize("ADD","Add");
					iButton.ToolTip                         =   btnText;
					if (!IsAddable)
					{
						iButton.Visible                     =   false;
					}
					else
					{
						iButton.Visible                     =   true;
						if (iButton is LinkButton)
						{
							LinkButton Button2              =   (LinkButton)StdAddButton;
							Button2.Click                   +=  new System.EventHandler(StdAddButton_Click);
							Button2.Text                    =   btnText;
						}
						else if (iButton is ImageButton)
						{
							ImageButton Button2             =   (ImageButton)StdAddButton;
							Button2.Click                   +=  new ImageClickEventHandler(StdAddImgButton_Click);
							Button2.AlternateText           =   btnText;
						}
						else if (iButton is Button)
						{
							((Button)iButton).Click         +=  new EventHandler(StdAddButton_Click);
							if ( string.IsNullOrEmpty(((Button)iButton).Text))
								((Button)iButton).Text      =   btnText;
						}
						StdButtonList.Add(iButton);
						iButton.EnableViewState = false;
					}
				}
				iButton                                     =   StdUpdateButton;
				if (iButton != null)
				{
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine("[V]PortalModuleControl OnInit StdUpdateButton found", ModuleTraceSwitch.Sw.Info);
					btnText                                 =   LocalizeHelper.Localize("UPDATE","Update");
					iButton.ToolTip                         =   btnText;
					if (iButton is LinkButton)
					{
						LinkButton Button2                  =   (LinkButton)StdUpdateButton;
						Button2.Click                       +=  new System.EventHandler(StdUpdateButton_Click);
						Button2.Text                        =   btnText;
					}
					else if (iButton is ImageButton)
					{
						ImageButton Button2                 =   (ImageButton)StdUpdateButton;
						Button2.Click                       +=  new ImageClickEventHandler(StdUpdateImgButton_Click);
						Button2.AlternateText               =   btnText;
					}
					else if (iButton is Button)
					{
						((Button)iButton).Click             +=  new EventHandler(StdUpdateButton_Click);
						if ( string.IsNullOrEmpty(((Button)iButton).Text))
							((Button)iButton).Text          =   btnText;
					}
					StdButtonList.Add(iButton);
					iButton.EnableViewState                 =   false;
				}

				iButton                                     =   StdSearchButton;
				if (iButton != null)
				{
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine("[V]PortalModuleControl OnInit StdSearchButton found", ModuleTraceSwitch.Sw.Info);
					btnText                                 =   LocalizeHelper.Localize("SEARCH","Search");
					iButton.ToolTip                         =   btnText;
					if (iButton is LinkButton)
					{
						LinkButton Button2                  =   (LinkButton)StdSearchButton;
						Button2.Click                       +=  new System.EventHandler(StdSearchButton_Click);
						Button2.Text                        =   btnText;
					}
					else if (iButton is ImageButton)
					{
						ImageButton Button2                 =   (ImageButton)StdSearchButton;
						Button2.Click                       +=  new ImageClickEventHandler(StdSearchImgButton_Click);
						Button2.AlternateText               =   btnText;
					}
					else if (iButton is Button)
					{
						((Button)iButton).Click             +=  new EventHandler(StdSearchButton_Click);
						if ( string.IsNullOrEmpty(((Button)iButton).Text))
							((Button)iButton).Text          =   btnText;
					}
					StdButtonList.Add(iButton);
					iButton.EnableViewState                 =   false;
				}
			}
			else //ReadOnly
			{
				WebControl iButton	                        =	StdDeleteButton;
				if( iButton != null)
					iButton.Visible                         =   false;
				iButton							            =	StdEditButton;
				if( iButton != null)
						iButton.Visible			            =   false;
				iButton							            =	StdAddButton;
				if( iButton != null)
						iButton.Visible			            =   false;
				iButton							            =	StdUpdateButton;
				if( iButton != null)
						iButton.Visible			            =   false;
				iButton							            =	StdSearchButton;
				if( iButton != null)
						iButton.Visible			            =   false;
			}

			BuildControlHierarchy();
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnInit Adding _header Count: {0}",_header.Controls.Count),ModuleTraceSwitch.Sw.Info);
			_headerPlaceHolder.Controls.Add(_header);
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnInit Adding _footer Count: {0}",_footer.Controls.Count),ModuleTraceSwitch.Sw.Info);
			Controls.Add(_footer);
			base.OnInit(e);
			bool ok                                         =   CheckLicense;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl OnInit END License: {0}, Demo: {1}", ok, IsDemo),ModuleTraceSwitch.Sw.Info);
		}

		protected override void OnPreRender(EventArgs e)
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]PortalModuleControl OnPreRender BEG.",ModuleTraceSwitch.Sw.Info);
			base.OnPreRender(e);
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]PortalModuleControl OnPreRender END.",ModuleTraceSwitch.Sw.Info);
		}


		#endregion control std handlers override

		#region Module Supports...

		/// <summary>
		/// Crm compatibility flag: V3, v4 or v3and v4
		/// Written in DB and tested on load
		/// </summary>
		public virtual VersionType ModuleType
		{
			get
			{
				return VersionType.CrmV3|VersionType.CrmV4;
			}
		}
		
		
		/// <summary>
		/// Return true if the module is an Admin Module, admin modules can't be uninstalled
		/// </summary>
		public virtual bool AdminModule
		{
			get
			{
				return false;
			}
		}
		
		/// <summary>
		/// Used to classify modules in RadComboModules and elsewhere
		/// When the module is an Admin Module, get replaced by Admin if not overriden
		/// Written in DB
		/// </summary>
		public virtual string Category
		{
			get
			{
				if ( AdminModule )
					return "Admin";
				return StStr.NormalModuleCat;
			}
		}

		/// <summary>
		/// Display name of category see Category Property
		/// When the module is an Admin Module, get replaced by Admin if not overriden
		/// </summary>
		public virtual string CategoryName
		{
			get
			{
				if ( AdminModule )
					return LocalizeHelper.Localize(StStr.ADMIN_MOD_CAT,DBAdmin);
				return LocalizeHelper.Localize(StStr.NORMAL_MOD_CAT,StStr.NormalModuleCat);
			}
		}

		/// <summary>
		/// When set to read only, triggers are not installed and modules buttons not displayed
		/// </summary>
		public virtual bool ReadOnly
		{
			get
			{
				return _ReadOnly;
			}
			set
			{
				_ReadOnly = value;
			}
		}

		/// <summary>
		/// Cachable modules are locally cached
		/// Use with care, no more tested since 2008
		/// Return true if the module is Cacheable.
		/// </summary>
		public virtual bool Cacheable
		{
			get
			{
				return _cacheable;
			}
			set
			{
				_cacheable = value;
			}
		}

		protected string _popUpOptions = "toolbar=1,location=0,directories=0,status=0,menubar=1,scrollbars=1,resizable=1,width=800,height=600,screenX=15,screenY=15,top=15,left=15";
		/// <summary>
		/// Builds Javascript popup command
		/// </summary>
		/// <returns>popup command as a string</returns>
		protected virtual string GetPopupCommand()
		{
			return ADNPage.GetPopupCommand(_popUpOptions);
		}

		protected virtual string PortalUrl()
		{
			return portalSettings.PortalUrl();
		}

		#region licenses

				
		/// <summary>
		/// Property to define in each class that must be checked for licenses
		/// return the type that has been generated in the license
		/// </summary>
		protected virtual Type TypeForLicence
		{
			get
			{
				return typeof(PortalModuleControl);
			}
		}


		/// <summary>
		/// Tests license validity for the type set in property TypeForLicence
		/// </summary>
		protected bool IsLicenseValid
		{
			get
			{
#if !DEBUG
				return LicenseManager.IsValid(TypeForLicence);
#else
			return true;
#endif
			}
		}
		/// <summary>
		/// Tests license validity for the type sent in parameter
		/// returns true or false and a license object
		/// </summary>
		protected bool GetLicenseValid(object ob,out License lic)
		{
#if !DEBUG
			return LicenseManager.IsValid(TypeForLicence,ob,out lic);
#else
			lic = null;
			return true;
#endif
		}

		/// <summary>
		/// Tests license validity for the type sent in parameters
		/// thrown an exception when no license
		/// </summary>
		protected void ValidateLicense()
		{
#if !DEBUG
			LicenseManager.Validate(TypeForLicence);
#endif
		}

		/// <summary>
		/// Tests license validity for the type and object sent in parameters
		/// thrown an exception when no license
		/// </summary>
		protected License ValidateLicence(object ob)
		{
#if !DEBUG
			return LicenseManager.Validate(TypeForLicence, ob);
#else
			return null;
#endif
		}

		#endregion licenses

		/// <summary>
		/// This property indicates if the specified module supports can be
		/// collpasable (minimized/maximized/closed)
		/// </summary>
		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public Boolean SupportCollapsable
		{
			get
			{
				return Config.SupportWindowMgmt && ModuleBaseConfiguration.SupportCollapsable;
			}
		} // end of SupportCollapsable

		/// <summary>
		/// This property indicates if the specified module supports a back button
		/// </summary>
		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public bool SupportsBack
		{
			get
			{
				return _supportsBack;
			}
			set
			{
				_supportsBack = value;
			}

		}

		
		/// <summary>
		/// This property indicates if the specified module supports arrows to move modules
		/// </summary>
		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public bool SupportsArrows
		{
			get
			{
				bool returnValue = _supportsArrows;

				if ( portalSettings.CustomSettings.ContainsKey(StStr.SiteSettingsShowModuleArrows) )
					returnValue =  returnValue && portalSettings.CustomSettings[StStr.SiteSettingsShowModuleArrows].ToBool();

				if ( Settings.ContainsKey(StStr.ModuleSettingsShowArrowButtons) )
					returnValue =  returnValue && Settings[StStr.ModuleSettingsShowArrowButtons].ToBool();
				return returnValue;
			}
			set
			{
				_supportsArrows = value;
			}
		}

		/// <summary>
		/// This property indicates if the specified module supports help
		/// </summary>
		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public bool SupportsHelp
		{
			get
			{
				if ( _supportsHelp )
					return true;

				if ( !string.IsNullOrEmpty(ModuleBaseConfiguration.DesktopSrc) && 
						Settings.ContainsKey(StStr.ModuleSettingsShowHelpButton) &&
						Settings[StStr.ModuleSettingsShowHelpButton].ToBool() 
					)
				{
					_supportsHelp   = File.Exists(HttpContext.Current.Server.MapPath(ModuleHelpPath));
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl supportsHelp GET: {0}.",_supportsHelp),ModuleTraceSwitch.Sw.Info);
				return _supportsHelp;
			}
		}

		public virtual string ModuleHelpPath
		{
			get
			{
				string strHelpPath  =   Config.HelpPath.TrimStart(new char[]{'~','/'}); // remove '~/'
				string aux          =   string.Format("{0}/{1}/AddonNice/{2}/{3}.xml",
					new object[]{Path2.ApplicationRoot,strHelpPath, ModuleBaseConfiguration.DesktopSrc.Replace(".", "_"),ModuleHelpFileName});
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ModuleHelpPath GET: {0}.",aux),ModuleTraceSwitch.Sw.Info);
				return aux;
			}
		}

		public virtual string ModuleHelpFileName
		{
			get
			{
					string aux          = ModuleBaseConfiguration.DesktopSrc.Replace(".","_").ToString();
					int fileNameStart   = aux.LastIndexOf("/");
					return aux.Substring(fileNameStart+1);
			}
		}

		public virtual string ModuleHelpCommand
		{
			get
			{
				string strHelpPath  =   Config.HelpPath.TrimStart(new char[]{'~','/'}); // remove '~/'
				string aux          =   ModuleBaseConfiguration.DesktopSrc.Replace(".","_").ToString();
				string fileName     =   ModuleHelpFileName;
				StringBuilder sb    =   new StringBuilder();
				sb.AppendFormat("{0}/{1}/HelpViewer.aspx?loc=AddonNice/{2}&src={3}",
					new object[]{Path2.ApplicationRoot,strHelpPath,aux,fileName}); 
				string cmd          =   sb.ToString();
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ModuleHelpCommand GET: {0}.",cmd),ModuleTraceSwitch.Sw.Info);
				return cmd;
			}
		}

		#endregion

		#region Portal
		/// <summary>
		/// Stores current portal settings 
		/// </summary>
		public PortalSettings portalSettings
		{
			get
			{
				ADNPage P    =   ADNPage;
				if ( P != null)
					return P.portalSettings;
				// Obtain PortalSettings from Current Context
				if ( !DesignMode )
					return (PortalSettings) HttpContext.Current.Items[StStr.strPortalSettings];
				// in designMode try loading portal '0'
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( "[V]PortalModuleControl portalSettings in DESIGN MODE LOADING Portal '0'",ModuleTraceSwitch.Sw.Info);
				return new PortalSettings(0);
			}
		}

		/// <summary>
		/// ID of portal in which module is instantiated
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public int PortalID 
		{
			get 
			{
				return _portalID;
			}
			set 
			{
				_portalID = value;
			}
		}
		
		#endregion

		#region Page


		// Set the various skins for moduleButtons
		public virtual void Page_PreInit(object sender, EventArgs e)
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Page_PreInit BEG Handler called sender: {0}", (sender is ADNPage) ? ((ADNPage)sender).PageID.ToString(): sender.ToString()),ModuleTraceSwitch.Sw.Info);
			// setup local layout
			SetupLayout();
			BuildButtonLists();
			MergeButtonLists();
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]PortalModuleControl Page_PreInit END Handler Ok",ModuleTraceSwitch.Sw.Info);
		}
		
		/// <summary>
		/// Returns the current Addonice page
		/// </summary>
		public AddonNice.UI.ADNPage ADNPage
		{
			get
			{
				System.Web.UI.Page p	=	base.Page;
				if (p is AddonNice.UI.ADNPage)
					return (AddonNice.UI.ADNPage) p;
				return null;
			}
		}

		// CS 20/11/04
		public System.Web.UI.Page BasePage
		{
			get
			{
				return	base.Page;
			}
		}
		
		/// <summary>
		/// Stores current item ID if applicable: extracted from query string "ItemID"
		/// Default to -1 if no set
		/// </summary>
		public int ItemID
		{
			get
			{
				if (_ItemID == -1)
				{
					try
					{
						if (HttpContext.Current != null)
						{
							object ob = Request.Params[StStr.strItemID];
							if (ob != null)
							{
								string str = (string)ob;
								if (str.IndexOf(',') != -1)
								{
									string[] matstr = str.Split(new char[] { ',' },StringSplitOptions.RemoveEmptyEntries);
									if ( ModuleTraceSwitch.Sw.TraceVerbose )
										Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ItemID  Params[\"ItemID\"]= {0}", str),ModuleTraceSwitch.Sw.Info);
									str = matstr[0];
								}
								_ItemID = Int32.Parse(str);
							}
						}
						if ( ModuleTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ItemID  set from Request= {0}", _ItemID),ModuleTraceSwitch.Sw.Info);
					}
					catch (Exception ex)
					{
						if ( ModuleTraceSwitch.Sw.TraceError )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl ItemID = {0}, ex: {1}", Request.Params["ItemID"], ex),ModuleTraceSwitch.Sw.Info);
					}
				}
				return _ItemID;
			}
		}

		/// <summary>
		/// Used by Edit/Add Pages
		/// Check if we are creating a new item, true if  ItemID is (-1), the default value
		/// ItemID is set by query string "ItemID"
		/// </summary>
		public bool isNewItem
		{
			get
			{
				return (_ItemID == -1);
			}
		}

		
		/// <summary>
		/// Stores current linked Page ID if applicable: extracted from query string "PageID"
		/// or from portalSettings.ActivePageSettings.PageID if no querystring, default to -1 if no set
		/// </summary>
		public int PageID
		{
			get
			{
				if (_PageID == -1)
				{
					try
					{
						// Determine PageID if specified
						if (HttpContext.Current != null)
						{
							_PageID = Portal.PageID;
						}
						if ( ModuleTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl PageID GET, set from Request= {0}", _PageID),ModuleTraceSwitch.Sw.Info);
					}
					catch (Exception ex)
					{
						if ( ModuleTraceSwitch.Sw.TraceError )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl PageID = {0}, ex: {1}", Request.Params["PageID"], ex),ModuleTraceSwitch.Sw.Info);
					}
					// CS 28/8/04
					if ( (_PageID == -1) || ( _PageID == StStr.PageIDNotAssigned ) )
					{
						if (Page != null && Page is ADNPage)
							_PageID = ((ADNPage)Page).PageID;
						if ( ModuleTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl PageID  set from Page= {0}", _PageID),ModuleTraceSwitch.Sw.Info);
					}
				}
				return _PageID;
			}
		}

		/// <summary>
		/// Stores current tab settings 
		/// </summary>
		public SettingsDictionary pageSettings
		{
			get
			{
				AddonNice.UI.ADNPage p =	ADNPage;
				if ( p != null)
					return p.Settings;
				return null;
			}
		}
		#endregion Page

		#region Title

		/// <summary>
		/// Switch to turn on/off the display of Title text.
		/// </summary>
		public virtual bool ShowTitle
		{
			get
			{
				if(HttpContext.Current != null) // if it is not design time
				{
					return bool.Parse(Settings[StStr.ModuleSettingsShowTitle].Value);
				}
				return false;
			}
			set
			{
				if(HttpContext.Current != null) // if it is not design time
				{
					if (Settings.ContainsKey(StStr.ModuleSettingsShowTitle))
						Settings[StStr.ModuleSettingsShowTitle].Value = value.ToString();
				}
			}
		}

		private string _titleText = string.Empty;
		/// <summary>
		/// The module title as it will be displayed on the page. Handles cultures automatically.
		/// </summary>
		public virtual string TitleText
		{
			get
			{

				if( _titleText == string.Empty && HttpContext.Current != null) // if it is not design time
				{
					string strlang = portalSettings.PortalContentLanguage.Name.ToUpper().Replace('-', '_');
					if ( portalSettings.PortalContentLanguage != CultureInfo.InvariantCulture
						&& Settings.ContainsKeyNotEmpty("MODULESETTINGS_TITLE_" + strlang)  )
					{
						_titleText = Settings["MODULESETTINGS_TITLE_" + strlang].Value;
					}
					else
					{
						if ( ModuleBaseConfiguration != null)
							_titleText = ModuleBaseConfiguration.ModuleTitle; 
						else
							_titleText = "TitleText Placeholder";
					}
					}
				return _titleText;
			}
			set
			{
				_titleText = value;
			}
		}

		private string _editText = "EDIT";
		private string _editUrl;
		private string _editTarget;
		/// <summary>
		/// Text for Edit Link
		/// </summary>
		public string EditText
		{
			get
			{
				return _editText;
			}
			set{_editText = value;}
		}
		/// <summary>
		/// Url for Edit Link
		/// </summary>
		public string EditUrl
		{
			get
			{
				return _editUrl;
			}
			set
			{
				_editUrl                =   value;
				if ( _editButton != null )
				{
					if ( _editUrl.IndexOf("?") >= 0 ) //Do not change if  the querystring is present
						_editButton.HRef =  _editUrl;
					else
						_editButton.HRef =  HttpUrlBuilder.BuildUrlWithCustomAttributes(_editUrl,PageID,"mID=" + ModuleID.ToString());
				}
			}
		}

		/// <summary>
		/// Target frame/page for Edit Link
		/// </summary>
		public string EditTarget
		{
			get
			{
				return _editTarget;
			}
			set{_editTarget = value;}
		}
		private string _addText = "ADD";
		private string _addUrl;
		private string _addTarget;

		/// <summary>
		/// Text for Add Link
		/// </summary>
		public string AddText
		{
			get
			{
				return _addText;
			}
			set
			{
				_addText = value;
			}
		}

		/// <summary>
		/// Url for Add Link
		/// </summary>
		public string AddUrl
		{
			get
			{
				return _addUrl;
			}
			set
			{
				_addUrl                 =   value;
				if ( _addButton != null )
				{
					if ( _addUrl.IndexOf("?") >= 0 ) //Do not change if  the querystring is present
						_addButton.HRef =   _addUrl;
					else
						_addButton.HRef =   HttpUrlBuilder.BuildUrlWithCustomAttributes(_addUrl,PageID,"mID=" + ModuleID.ToString());
				}
			}
		}

		/// <summary>
		/// Target frame/page for Add Link
		/// </summary>
		public string AddTarget
		{
			get
			{
				return _addTarget;

			}
			set{_addTarget = value;}
		}

		private string _propertiesText = "PROPERTIES";
		private string _propertiesUrl = Config.ModulesPath+"/"+Config.ModulePropertyPage;
		private string _propertiesTarget;

		/// <summary>
		/// Text for Properties Link
		/// </summary>
		public string PropertiesText
		{
			get
			{
				return _propertiesText;
			}
			set
			{
				_propertiesText = value;
			}
		}

		/// <summary>
		/// Url for Properties Link 
		/// </summary>
		public string PropertiesUrl
		{
			get
			{
				return _propertiesUrl;
			}
			set
			{
				_propertiesUrl   =   value;
			}
		}

		/// <summary>
		/// Target frame/page for Properties Link
		/// </summary>
		public string PropertiesTarget
		{
			get
			{
				return _propertiesTarget;
			}
			set
			{
				_propertiesTarget = value;
			}
		}

		private string _securityText = "SECURITY";
		private string _securityUrl = Config.ModulesPath+"/"+Config.ModuleSettingsPage;
		private string _securityTarget;

		/// <summary>
		/// Text for Security Link
		/// </summary>
		public string SecurityText
		{
			get
			{
				return _securityText;
			}
			set{_securityText = value;}
		}

		/// <summary>
		/// Url for Security Link
		/// </summary>
		public string SecurityUrl
		{
			get
			{
				return _securityUrl;
			}
		}

		/// <summary>
		/// Target frame/page for Security Link
		/// </summary>
		public string SecurityTarget
		{
			get
			{
				return _securityTarget;
			}
			set{_securityTarget = value;}
		}

		#endregion Title

		#region ModuleButtons : they are controls dedicated to the module management

		private ModuleButton.RenderOptions _buttonsRenderAs = ModuleButton.RenderOptions.NotSet;
		/// <summary>
		/// Determines how ModuleButtons are rendered: as TextOnly, TextAndImage or ImageOnly. ImageOnly is the 'classic' AddonNice style.
		/// </summary>
		public ModuleButton.RenderOptions ButtonsRenderAs
		{
			get
			{
				if (_buttonsRenderAs == ModuleButton.RenderOptions.NotSet)
				{
					if (HttpContext.Current != null) // if it is not design time
					{
						if (Settings.ContainsKeyNotEmpty(StStr.ModuleSettingsButtonDisplay))
							_buttonsRenderAs =   (ModuleButton.RenderOptions)Settings[StStr.ModuleSettingsButtonDisplay].ToInt();
					}
				}
				else _buttonsRenderAs        =   ModuleButton.RenderOptions.ImageOnly;
				return _buttonsRenderAs;
			}
			set
			{
				_buttonsRenderAs             =   value;
			}
		}

		private ModuleButton _propertiesButton;
		/// <summary>
		/// Module Properties button
		/// </summary>
		public ModuleButton PropertiesButton
		{
			get
			{
				if ( _propertiesButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanProperties )
					{
						// create the button
						_propertiesButton                   =   new ModuleButton();
						_propertiesButton.ID                =   string.Format("PMB_{0}",ModuleID);
						_propertiesButton.Group             =   ModuleButton.ButtonGroup.Admin;
						_propertiesButton.EnglishName       =   "Properties";
						_propertiesButton.TranslationKey    =   "PROPERTIES";
						_propertiesButton.PopUp             =   Settings[StStr.ModuleSettingsModuleButtonsAsPopup].ToBool();
						_propertiesButton.ImageSkin         =   "Buttons_Properties";
						if(PropertiesUrl.IndexOf("?") >= 0) //Do not change if  the querystring is present (shortcut patch)
							_propertiesButton.HRef          =   PropertiesUrl;
						else
							_propertiesButton.HRef          =   HttpUrlBuilder.BuildUrlWithCustomAttributes(PropertiesUrl, PageID, "mID=" + ModuleID.ToString());
						_propertiesButton.Target            =   PropertiesTarget;
						_propertiesButton.RenderAs          =   ButtonsRenderAs;
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _propertiesButton Created ButtonTargetPane:{0}", PropertiesTarget),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _propertiesButton;
			}
		}

		private ModuleButton _securityButton;
		/// <summary>
		/// Module Security button
		/// </summary>
		public ModuleButton SecurityButton
		{
			get
			{
				if ( _securityButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanSecurity )
					{
						// create the button
						_securityButton					    =   new ModuleButton();
						_securityButton.ID                  =   string.Format("SMB_{0}",ModuleID);
						_securityButton.Group			    =   ModuleButton.ButtonGroup.Admin;
						_securityButton.EnglishName		    =   "Security";
						_securityButton.PopUp               =   Settings[StStr.ModuleSettingsModuleButtonsAsPopup].ToBool();
						_securityButton.TranslationKey	    =   "SECURITY";
						_securityButton.ImageSkin           =   "Buttons_Security";
						if(SecurityUrl.IndexOf("?") >= 0) //Do not change if  the querystring is present (shortcut patch)
							_securityButton.HRef            =   SecurityUrl;
						else
							_securityButton.HRef            =   HttpUrlBuilder.BuildUrlWithCustomAttributes(SecurityUrl, PageID, "mID=" + ModuleID.ToString());
						_securityButton.Target              =   SecurityTarget;
						_securityButton.RenderAs            =   ButtonsRenderAs;
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _securityButton Created ButtonTargetPane:{0}", SecurityTarget),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _securityButton;
			}
		}

		private ModuleButton _deleteModuleButton;
		/// <summary>
		/// "Delete this Module" button
		/// </summary>
		public ModuleButton DeleteModuleButton
		{
			get
			{
				if ( _deleteModuleButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanDeleteModule  )
					{
						// create the button
						string strPane                      =   ModuleBaseConfiguration.PaneName.ToLower(CultureInfo.InvariantCulture);
						_deleteModuleButton                 =   new ModuleButton();
						_deleteModuleButton.ID              =   string.Format("DMB_{0}",ModuleID);
						_deleteModuleButton.Group           =   ModuleButton.ButtonGroup.Admin;
						_deleteModuleButton.TranslationKey  =   "DELETEMODULE";
						_deleteModuleButton.EnglishName     =   "Delete this module";
						_deleteModuleButton.ImageSkin       =   "Buttons_DeleteModule";
						_deleteModuleButton.RenderAs        =   ButtonsRenderAs;
						_deleteModuleButton.Attributes.Add("pane", strPane);
						string msg                          =   LocalizeHelper.Localize("MODULE_CONFIRM_DELETE", "Delete this module ?");
						string strtitle                     =   LocalizeHelper.Localize("DELETE2", "Delete");
						if ( ModuleTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]PortalModuleControl DeleteModuleButton GET RegisterClientConfirm",ModuleTraceSwitch.Sw.Info);
						ADNPage.setClientConfirmAttributes(_deleteModuleButton,msg,strtitle);
						_deleteModuleButton.ServerClick     +=  new EventHandler(DeleteModuleButton_Click);
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _deleteModuleButton Created ButtonTargetPane:{0}", strPane),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _deleteModuleButton;
			}
		}

		private ModuleButton _helpButton;
		/// <summary>
		/// Module button that will launch the module help in a pop-up window
		/// </summary>
		public ModuleButton HelpButton
		{
			get
			{
				if ( _helpButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanHelp )
					{
					
						// create the button
						_helpButton                     =   new ModuleButton();
						_helpButton.ID                  =   string.Format("HMB_{0}",ModuleID);
						_helpButton.Group               =   ModuleButton.ButtonGroup.User;
						_helpButton.TranslationKey      =   "BTN_HELP";
						_helpButton.EnglishName         =   "Help";
						_helpButton.ImageSkin           =   "Buttons_Help";
						_helpButton.HRef                =   ModuleHelpCommand;
						_helpButton.PopUp               =   true;
						_helpButton.Target              =   "AddonNiceHelp";
						_helpButton.PopUpOptions        =   "toolbar=1,location=0,directories=0,status=0,menubar=1,scrollbars=1,resizable=1,width=600,height=400,screenX=15,screenY=15,top=15,left=15";
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _helpButton Created url:{0}", _helpButton.HRef),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _helpButton;
			}
		}

		// custom buttons from module developer enhancement 
		private ModuleButton _upButton;
		/// <summary>
		/// Module Up button
		/// </summary>
		public ModuleButton UpButton
		{
			get
			{
				if ( _upButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanArrows && ModuleBaseConfiguration.ModuleOrder != 1 )
					{
						// create the button
						string strPane                      =   ModuleBaseConfiguration.PaneName.ToLower(CultureInfo.InvariantCulture);
						_upButton                           =   new ModuleButton();
						_upButton.ID                        =   string.Format("UMB_{0}",ModuleID);
						_upButton.CausesValidation          =   false;
						_upButton.Group                     =   ModuleButton.ButtonGroup.Admin;
						_upButton.TranslationKey            =   "MOVE_UP";
						_upButton.EnglishName               =   "Move up";
						_upButton.ImageSkin                 =   "Buttons_Up";
						_upButton.Attributes.Add("direction","up");
						_upButton.Attributes.Add("pane", strPane);
						_upButton.RenderAs                  =   ButtonsRenderAs;
						_upButton.ServerClick               +=  new EventHandler(UpDown_Click);
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _upButton Created ButtonTargetPane:{0}", strPane),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _upButton;
			}
		}

		private ModuleButton _downButton;
		/// <summary>
		/// Module Down button
		/// </summary>
		public ModuleButton DownButton
		{
			get
			{
				if ( _downButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanArrows )
					{
						string strPane                  =   ModuleBaseConfiguration.PaneName.ToLower(CultureInfo.InvariantCulture);
						ArrayList sourceList            =   GetModules(strPane);
						ModuleItem m                    =   (ModuleItem)sourceList[sourceList.Count - 1];
						if ( ModuleBaseConfiguration.ModuleOrder != m.Order )
						{
							// create the button
							_downButton                     =   new ModuleButton();
							_downButton.ID                  =   string.Format("DWMB_{0}",ModuleID);
							_downButton.CausesValidation    =   false;
							_downButton.Group               =   ModuleButton.ButtonGroup.Admin;
							_downButton.TranslationKey      =   "MOVE_DOWN";
							_downButton.EnglishName         =   "Move down";
							_downButton.ImageSkin           =   "Buttons_Down";
							_downButton.Attributes.Add("direction","down");
							_downButton.Attributes.Add("pane", strPane);
							_downButton.RenderAs            =   ButtonsRenderAs;
							_downButton.ServerClick         +=  new EventHandler(UpDown_Click);
							if ( ButtonTraceSwitch.Sw.TraceVerbose )
								Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _downButton Created ButtonTargetPane:{0}", strPane),ButtonTraceSwitch.Sw.Info);
						}
					}
				}
				return _downButton;
			}
		}

		private ModuleButton _leftButton;
		/// <summary>
		/// Module Left button
		/// </summary>
		public ModuleButton LeftButton
		{
			get
			{
				if ( _leftButton == null && HttpContext.Current != null )
				{
					// check authority
					string strPane                                  =   ModuleBaseConfiguration.PaneName.ToLower(CultureInfo.InvariantCulture);
					if (CanArrows && strPane != StStr.leftPane)
					{
						string buttonTargetPane                     =   StStr.contentPane;
						if ( strPane == StStr.contentPane)
							buttonTargetPane                        =   StStr.leftPane;
						else if ( strPane == StStr.rightPane)
							buttonTargetPane                        =   StStr.contentPane;

						// create the button
						_leftButton                                 =   new ModuleButton();
						_leftButton.ID                              =   string.Format("LMB_{0}",ModuleID);
						_leftButton.CausesValidation                =   false;
						_leftButton.Group                           =   ModuleButton.ButtonGroup.Admin;
						_leftButton.TranslationKey                  =   "MOVE_LEFT";
						_leftButton.EnglishName                     =   "Move left";
						_leftButton.ImageSkin                       =   "Buttons_Left";
						_leftButton.Attributes.Add("sourcepane", strPane);
						_leftButton.Attributes.Add("targetpane",buttonTargetPane);
						_leftButton.RenderAs                        =   ButtonsRenderAs;
						_leftButton.ServerClick                     +=  new EventHandler(RightLeft_Click);
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl LeftButton Created ButtonTargetPane:{0}", buttonTargetPane),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _leftButton;
			}
		}

		private ModuleButton _rightButton;
		/// <summary>
		/// Module Right button
		/// </summary>
		public ModuleButton RightButton
		{
			get
			{
				if ( _rightButton == null && HttpContext.Current != null )
				{
					// check authority
					string strPane                          =       ModuleBaseConfiguration.PaneName.ToLower(CultureInfo.InvariantCulture);
					if (CanArrows && strPane != StStr.rightPane)
					{
						string buttonTargetPane             =   StStr.contentPane;
						if ( strPane == StStr.contentPane )
							buttonTargetPane                =   StStr.rightPane;
						else if ( strPane == StStr.leftPane )
							buttonTargetPane                =   StStr.contentPane;

						// create the button
						_rightButton                        =   new ModuleButton();
						_rightButton.ID                     =   string.Format("RMB_{0}",ModuleID);
						_rightButton.CausesValidation       =   false;
						_rightButton.Group                  =   ModuleButton.ButtonGroup.Admin;
						_rightButton.TranslationKey         =   "MOVE_RIGHT";
						_rightButton.EnglishName            =   "Move right";
						_rightButton.ImageSkin              =   "Buttons_Right";
						_rightButton.Attributes.Add("sourcepane", strPane);
						_rightButton.Attributes.Add("targetpane",buttonTargetPane);
						_rightButton.RenderAs               =   ButtonsRenderAs;
						_rightButton.ServerClick            +=  new EventHandler(RightLeft_Click);
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl RightButton Created TargetPane:{0}", buttonTargetPane),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _rightButton;
			}
		}


		private ModuleButton _editButton;
		/// <summary>
		/// Module edit button
		/// </summary>
		public ModuleButton EditButton
		{
			get
			{
				if ( _editButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanEdit )
					{
						// create the button
						_editButton                         =   new ModuleButton();
						_editButton.ID                      =   string.Format("EMB_{0}",ModuleID);
						_editButton.Group                   =   ModuleButton.ButtonGroup.Admin;
						_editButton.TranslationKey          =   EditText;
						_editButton.EnglishName             =   "Edit";
						_editButton.PopUp                   =   Settings[StStr.ModuleSettingsModuleButtonsAsPopup].ToBool();
						if(EditUrl.IndexOf("?") >= 0) //Do not change if  the querystring is present
							_editButton.HRef                =   EditUrl;
						else
							_editButton.HRef                =   HttpUrlBuilder.BuildUrlWithCustomAttributes(EditUrl, PageID, "mID=" + ModuleID.ToString());
						_editButton.Target                  =   EditTarget;
						_editButton.ImageSkin               =   "Buttons_Edit";
						_editButton.RenderAs                =   ButtonsRenderAs;
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _editButton Created Target:{0}", EditTarget),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _editButton;
			}
		}

		private ModuleButton _addButton;
		/// <summary>
		/// Module Add button
		/// </summary>
		public ModuleButton AddButton
		{
			get
			{
				if ( _addButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanAdd )
					{
						// create the button
						_addButton                      =   new ModuleButton();
						_addButton.ID                   =   string.Format("AMB_{0}",ModuleID);
						_addButton.Group                =   ModuleButton.ButtonGroup.User;
						_addButton.TranslationKey       =   AddText;
						_addButton.EnglishName          =   "Add";
						_addButton.PopUp                =   Settings[StStr.ModuleSettingsModuleButtonsAsPopup].ToBool();
						if(AddUrl.IndexOf("?") >= 0) //Do not change if  the querystring is present
							AddButton.HRef              =   AddUrl;
						else
							AddButton.HRef              =   HttpUrlBuilder.BuildUrlWithCustomAttributes(AddUrl, PageID, "mID=" + ModuleID.ToString());
						_addButton.Target               =   AddTarget;
						_addButton.ImageSkin            =   "Buttons_Add";
						_addButton.RenderAs             =   ButtonsRenderAs;
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _addButton Created Target:{0}", AddTarget),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _addButton;
			}
		}

		private ModuleButton _backButton;
		/// <summary>
		/// Module button that will return to previous tab
		/// </summary>
		public ModuleButton BackButton
		{
			get
			{
				if ( _backButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( CanBack )
					{
						// create the button
						_backButton                     =   new ModuleButton();
						_backButton.ID                  =   string.Format("BMB_{0}",ModuleID);
						_backButton.Group               =   ModuleButton.ButtonGroup.User;
						_backButton.TranslationKey      =   "BTN_BACK";
						_backButton.EnglishName         =   "Back to previous page";
						_backButton.HRef                =   Request.UrlReferrer.ToString();
						_backButton.ImageSkin           =   "Buttons_Back";
						_backButton.RenderAs            =   ButtonsRenderAs;
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl _backButton Created HRef:{0}", _backButton.HRef),ButtonTraceSwitch.Sw.Info);
					}
				}
				return _backButton;
			}
		}


		private LinkButton _minMaxButton = null;
		/// <summary>
		/// Module button to minimize/maximize module
		/// </summary>
		public LinkButton MinMaxButton
		{
			get
			{
				if ( _minMaxButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( _vcm != null && !UserDesktop.isClosed(_vcm.ModuleID) && CanMinimized )
					{
					
						// create the button based on current view
						if ( !UserDesktop.isMinimized(_vcm.ModuleID) )
							_minMaxButton =_vcm.create(WindowStateStrings.ButtonMinName,WindowStateStrings.ButtonMinLocalized);
						else 
						{
							_minMaxButton =_vcm.create(WindowStateStrings.ButtonMaxName,WindowStateStrings.ButtonMaxLocalized);
							// we are minimized -- show the user a hint by changing the color [future]
							// min_hint_ = true;
						}
						
						// set additional button properties
						_minMaxButton.CssClass = "adn_mod_btn";
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]PortalModuleControl _minMaxButton Created",ButtonTraceSwitch.Sw.Info);
					}
				}
				return _minMaxButton;
			}
		}

		private LinkButton _closeButton = null;
		/// <summary>
		/// Module button to close module
		/// </summary>
		public LinkButton CloseButton
		{
			get
			{
				if ( _closeButton == null && HttpContext.Current != null )
				{
					// check authority
					if ( _vcm != null 
						&& !UserDesktop.isClosed(_vcm.ModuleID) 
						&& CanClose 
						&& Config.SupportWindowMgmtClose )
					{
						// create the button
						_closeButton =_vcm.create(WindowStateStrings.ButtonCloseName,WindowStateStrings.ButtonClosedLocalized);	

						// set attribute to confirm delete
						string msg      =   LocalizeHelper.Localize("CONFIRM_CLOSE_MSG","Confirm Close");
						string title    =   LocalizeHelper.Localize("CONFIRM_CLOSE_TITLE","Close Window");
						ADNPage.setClientConfirmAttributes(_closeButton,msg,title);
						
						// set additional button properties
						_closeButton.CssClass = "adn_mod_btn";
						if ( ButtonTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]PortalModuleControl _closeButton Created.",ButtonTraceSwitch.Sw.Info);
					}
				}
				return _closeButton;
			}
		}
		#endregion ModuleButtons : they are controls dedicated to the module management

		#region User Authentication

		protected bool UserLogged
		{
			get
			{
				/* Changed to have similar API with StdAuxPage
				if ( portalSettings.AuthMode == AuthenticationMode.Forms )
					return (HttpContext.Current.User.Identity.Name.Length > 0);
				return true;
				 * */
				AuthenticationMode md   =   Config.AuthenticationMode;
				bool strace             =   ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose );
				if ( strace )
				{
					string info         =   SecurityTraceSwitch.Sw.Info;
					if (AuthenticationTrace.Sw.TraceVerbose )
						info            =   AuthenticationTrace.Sw.Info;
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]StdAuxPage UserLogged GET BEG AuthenticationMode: {0}.",md),info);
				}
				bool ret                =   false;
				if ( md == AuthenticationMode.Forms)
					ret                 =   HttpContext.Current.Request.IsAuthenticated;
				else if ( md == AuthenticationMode.Windows)
					ret                 =   HttpContext.Current.Request.LogonUserIdentity.IsAuthenticated;
				if ( strace )
				{
					string info         =   SecurityTraceSwitch.Sw.Info;
					if (AuthenticationTrace.Sw.TraceVerbose )
						info            =   AuthenticationTrace.Sw.Info;
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]StdAuxPage UserLogged GET END ret: {0}.",ret),info);
				}
				return ret;
			}
		}

		#endregion User Authentication

		#region Permissions
		/// <summary>
		/// View permission
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool IsViewable 
		{
			get 
			{
				if( string.IsNullOrEmpty(ModuleBaseConfiguration.AuthorizedViewRoles) )
					return false;

				// Perform tri-state switch check to avoid having to perform a security
				// role lookup on every property access (instead caching the result)
				if ( _canView == 0 ) 
				{
					// CRM Admin has all rights
					if (isUserInAdminRole ||
							PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedViewRoles)) 
					{
						_canView = 1;
					}
					else 
					{
						_canView = 2;
					}
				}
				return (_canView == 1);
			}
		}

		/// <summary>
		/// Add permission will be checked even when no link for edit button exists
		/// Contrary from CanAdd
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool IsAddable
		{
			get 
			{
				if( string.IsNullOrEmpty(ModuleBaseConfiguration.AuthorizedAddRoles) )
					return false;

				// Perform tri-state switch check to avoid having to perform a security
				// role lookup on every property access (instead caching the result)
				if ( _canAdd == 0 ) 
				{
					// CRM Admin has all rights
					if (isUserInAdminRole ||
								PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedAddRoles)) 
						{
							_canAdd = 1;
						}
						else 
						{
							_canAdd = 2;
						}
				}
				return (_canAdd == 1);
			}
		}

		/// <summary>
		/// Edit permission
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool IsEditable 
		{
			get 
			{
				if (string.IsNullOrEmpty(ModuleBaseConfiguration.AuthorizedEditRoles))
				{
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( "[V]PortalModuleControl IsEditable false",ModuleTraceSwitch.Sw.Info);
					return false;
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl IsEditable AuthorizedEditRoles: {0}", ModuleBaseConfiguration.AuthorizedEditRoles),ModuleTraceSwitch.Sw.Info);

				// Perform tri-state switch check to avoid having to perform a security
				// role lookup on every property access (instead caching the result)
				if ( _canEdit == 0 ) 
				{
					// CRM Admin has all rights
					if (isUserInAdminRole ||
							PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedEditRoles))
						{
							_canEdit = 1;
						}
						else 
						{
							_canEdit = 2;
						}
				}
				bool ret	=	(_canEdit == 1);
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl IsEditable: {0}", ret),ModuleTraceSwitch.Sw.Info);
				return ret;
			}
		}

		/// <summary>
		/// Delete permission do not need a delete link
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool IsDeletable
		{
			get 
			{
				if(string.IsNullOrEmpty(ModuleBaseConfiguration.AuthorizedDeleteRoles) )
				{
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( "[V]PortalModuleControl IsDeletable false",ModuleTraceSwitch.Sw.Info);
					return false;
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl IsDeletable AuthorizedDeleteRoles: {0}", ModuleBaseConfiguration.AuthorizedDeleteRoles),ModuleTraceSwitch.Sw.Info);

				// Perform tri-state switch check to avoid having to perform a security
				// role lookup on every property access (instead caching the result)
				if ( _canDelete == 0 ) 
				{
					// CRM Admin has all rights
					if (isUserInAdminRole ||
							PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedDeleteRoles)) 
						{
							_canDelete = 1;
						}
						else 
						{
							_canDelete = 2;
						}
				}
				bool ret	= (_canDelete == 1);
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl IsDeletable: {0}",ret),ModuleTraceSwitch.Sw.Info);
				return ret;
			}
		}

		/// <summary>
		/// Edit properties permission
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool ArePropertiesEditable
		{
			get 
			{
				if(string.IsNullOrEmpty(ModuleBaseConfiguration.AuthorizedPropertiesRoles) )
				{
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( "[V]PortalModuleControl ArePropertiesEditable false",ModuleTraceSwitch.Sw.Info);
					return false;
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ArePropertiesEditable AuthorizedPropertiesRoles: {0}", ModuleBaseConfiguration.AuthorizedPropertiesRoles),ModuleTraceSwitch.Sw.Info);

				// Perform tri-state switch check to avoid having to perform a security
				// role lookup on every property access (instead caching the result)
				if ( _canProperties == 0 ) 
				{
					// CRM Admin has all rights
					if ( isUserInAdminRole ||
						PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedPropertiesRoles)) 
					{
						_canProperties = 1;
					}
					else 
					{
						_canProperties = 2;
					}
				}
				bool ret	= (_canProperties == 1);
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ArePropertiesEditable: {0}", ret),ModuleTraceSwitch.Sw.Info);
				return ret;
			}
		}

		/// <summary>
		/// Minimize permission
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanMinimized 
		{
			get 
			{
				// Perform tri-state switch check to avoid having to perform a security
				// role lookup on every property access (instead caching the result)
				if ( _canMin== 0 ) 
				{
					// CRM Admin has all rights
					if (isUserInAdminRole ||
							PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedViewRoles)) 
					{
						_canMin = 1;
					}
					else 
					{
						_canMin = 2;
					}
				}
				return (_canMin == 1);
			}
		} // end of CanMinimized

		/// <summary>
		/// Close permission
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanClose
		{
			get 
			{
				// Perform tri-state switch check to avoid having to perform a security
				// role lookup on every property access (instead caching the result)
				if ( _canClose == 0 ) 
				{
					// CRM Admin has all rights
					if (isUserInAdminRole ||
						PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedDeleteModuleRoles)) 
					{
						_canClose = 1;
					}
					else 
					{
						_canClose = 2;
					}
				}
				return (_canClose == 1);
			}
		} // end of CanClose


		/// <summary>
		/// Permission for DeleteModuleButton
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanDeleteModule
		{
			get 
			{
				// CRM Admin has all rights
				if ( (isUserInAdminRole ||
						PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedDeleteModuleRoles)) 
					&& portalSettings.ActivePageSettings.PageID == ModuleBaseConfiguration.PageID )
					return true;
				return false;
			}
		}


		/// <summary>
		/// Permission for HelpButton
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public bool CanHelp
		{
			get 
			{
				if ( SupportsHelp && ( isUserInAdminRole ||
						(PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedEditRoles)) ||
						(PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedAddRoles)) ||
						(PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedDeleteRoles)) ||
						(PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedPropertiesRoles)) ) 
					)
					return true;
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( "[V]PortalModuleControl CanHelp false",ModuleTraceSwitch.Sw.Info);
				return false;
			}
		}


		/// <summary>
		/// Permission for BackButton
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanBack
		{
			get 
			{
				if ( SupportsBack 
					&& ShowBack 
					&& Request.UrlReferrer != null )
				{
					return true;
				}
				return false;
			}
		}

		/// <summary>
		/// Permission for EditButton : also check an Edit  link exists
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanEdit
		{
			get 
			{
				if ( portalSettings.ActivePageSettings.PageID != ModuleBaseConfiguration.PageID ) 
				{
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( "[V]PortalModuleControl CanEdit false.",ModuleTraceSwitch.Sw.Info);
					return false;
				}

				bool ret	=	(!string.IsNullOrEmpty(EditUrl)
					//&& (isUserInAdminRole || PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedEditRoles)) );
					&& IsEditable );
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl CanEdit: {0}", ret),ModuleTraceSwitch.Sw.Info);
				return ret;
			}
		}

		/// <summary>
		/// Permission for AddButton
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanAdd
		{
			get 
			{
				bool ret = false;
				if (ModuleBaseConfiguration != null && portalSettings.ActivePageSettings.PageID == ModuleBaseConfiguration.PageID)
				{
					if (!string.IsNullOrEmpty(AddUrl) 
						//&& (isUserInAdminRole || PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedAddRoles)))
						&& IsAddable )
						ret = true;
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl CanAdd {0}, AddUrl: {1}", ret,_addUrl),ModuleTraceSwitch.Sw.Info);
				return ret;
			}
		}


		/// <summary>
		/// Permission for Arrow Buttons (Up/Down/Left/Right)
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanArrows
		{
			get 
			{
				if ( ModuleBaseConfiguration == null || ModuleID == StStr.ModuleIDNotAssigned ) 
					return false;

				return ( SupportsArrows 
					&& portalSettings.ActivePageSettings.PageID == ModuleBaseConfiguration.PageID
					&&( isUserInAdminRole || PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedMoveModuleRoles) ));
			}
		}

		/// <summary>
		/// Permission for Security Button
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanSecurity
		{
			get 
			{
				if ( ModuleBaseConfiguration == null || portalSettings.ActivePageSettings.PageID != ModuleBaseConfiguration.PageID ) 
					return false;

				return ( !string.IsNullOrEmpty(SecurityUrl )
					&& ( isUserInAdminRole || PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedPropertiesRoles) ));
			}
		}

		/// <summary>
		/// Permission for Properties Button
		/// </summary>
		[
		Browsable(false), 
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		public virtual bool CanProperties
		{
			get 
			{
				if (ModuleBaseConfiguration == null || portalSettings.ActivePageSettings.PageID != ModuleBaseConfiguration.PageID)
					return false;

				return ( !string.IsNullOrEmpty(PropertiesUrl)
					&& ( isUserInAdminRole || PortalSecurity.IsUserInRoles(ModuleBaseConfiguration.AuthorizedPropertiesRoles) ));
			}
		}

		private bool _showBack = false;
		/// <summary>
		/// Can be set from module code to indicate whether module should display Back button
		/// </summary>
		public bool ShowBack
		{
			get
			{
				return _showBack;
			}
			set
			{
				_showBack = value;
			}
		}
		#endregion Permissions
		
		#region Arrow buttons functions
		/// <summary>
		/// function for module moving
		/// </summary>
		private ModuleConfiguration GetModule()
		{
			// Obtain selected module data
			// get the portal setting at the Tab level and not from this class as it is not refreshed
			foreach (ModuleConfiguration _module in ADNPage.portalSettings.ActivePageSettings.Modules) 
			{
				if (_module.ModuleID == OriginalModuleID)  // OriginalModuleID to have it work with shortcut module
					return _module;
			}
			return null;
		}

		/// <summary>
		/// function for module moving
		/// </summary>
		private void OrderModules (ArrayList list) 
		{
			int i = 1;
		
			// sort the arraylist
			list.Sort();
		
			// renumber the order
			foreach (ModuleItem m in list) 
			{
				// number the items 1, 3, 5, etc. to provide an empty order
				// number when moving items up and down in the list.
				m.Order = i;
				i += 2;
			}
		}

		/// <summary>
		/// The GetModules helper method is used to get the modules
		/// for a single pane within the tab
		/// </summary>
		private ArrayList GetModules (string pane) 
		{
			ArrayList paneModules       =   new ArrayList();
			string p	                =	pane.ToLower(CultureInfo.InvariantCulture);
			// get the portal setting at the Tab level and not from this class as it is not refreshed
			foreach (ModuleConfiguration _module in ADNPage.portalSettings.ActivePageSettings.Modules) 
			{
				if ( portalSettings.ActivePageSettings.PageID == _module.PageID &&
					_module.PaneName.ToLower(CultureInfo.InvariantCulture) == p ) 
				{
					ModuleItem      m	=   new ModuleItem();
					m.Title             =   _module.ModuleTitle;
					m.ID                =   _module.ModuleID;      
					m.ModuleDefID       =   _module.ModuleDefID;
					m.Order             =   _module.ModuleOrder;
					m.PaneName          =   _module.PaneName;   
					m.ModuleGuid        =   _module.GuidID;
					paneModules.Add(m);
				}
			}
		
			return paneModules;
		}

		/// <summary>
		/// function for module moving
		/// </summary>
		private string AppendModuleID (string url, int moduleID)
		{
			// Sometimes the home page does not have parameters 
			// so we test for both & and ?
			int selectedModIDPos    =   url.IndexOf("&selectedmodid");
			int selectedModIDPos2   =   url.IndexOf("?selectedmodid");
			if(selectedModIDPos >= 0)
			{
				int selectedModIDEndPos = url.IndexOf("&", selectedModIDPos + 1);
				if(selectedModIDEndPos >= 0)
				{
					return url.Substring(0, selectedModIDPos) + "&selectedmodid=" + moduleID + url.Substring(selectedModIDEndPos);
				}
				return url.Substring(0, selectedModIDPos) + "&selectedmodid=" + moduleID;
			}
			else if(selectedModIDPos2 >= 0)
			{
				int selectedModIDEndPos2 = url.IndexOf("?", selectedModIDPos2 + 1);
				if(selectedModIDEndPos2 >= 0)
				{
					return url.Substring(0, selectedModIDPos2) + "?selectedmodid=" + moduleID + url.Substring(selectedModIDEndPos2);
				}
				return url.Substring(0, selectedModIDPos2) + "?selectedmodid=" + moduleID;
			}
			if(url.IndexOf("?") >= 0)
			{
				return url + "&selectedmodid=" + moduleID;
			}
			return url + "?selectedmodid=" + moduleID;
		}

		/// <summary>
		/// Redirect to the same page to pick up changes
		/// </summary>
		void RedirectToSamePage(bool appendModule)
		{
			/*
			string redirectUrl  =   string.Empty;
			Stack<string> stk   =   ADNPage.ReturnUrlStk;
			if (stk.Count > 0)
				redirectUrl     =   stk.Pop();
			if ( PageTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl RedirectToSamePage redirectUrl: '{0}'",redirectUrl),PageTraceSwitch.Sw.Info);
			if (redirectUrl != string.Empty)
			{
				if ( appendModule )
					Response.Redirect(AppendModuleID(redirectUrl, ModuleID));
				Response.Redirect(redirectUrl);
			}
			// old code
			 * */
			string redirectUrl      =   string.Empty;
			if ( appendModule )
					redirectUrl     =   AppendModuleID(Page.Request.RawUrl, ModuleID);		
			else    redirectUrl     =   Page.Request.RawUrl;
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl RedirectToSamePage END Redirect Url: '{0}'.", redirectUrl), ModuleTraceSwitch.Sw.Info);
			//Response.Redirect(redirectUrl);
			ADNPage.Redirect(redirectUrl,true);
		}

		/// <summary>
		/// The RightLeft_Click server event handler on this page is
		/// used to move a portal module between layout panes on
		/// </summary>
		private void RightLeft_Click(Object sender, EventArgs e) 
		{
			string sourcePane       =   ((ModuleButton)sender).Attributes["sourcepane"];
			string targetPane       =   ((ModuleButton)sender).Attributes["targetpane"];

			// get source arraylist
			ArrayList sourceList    =   GetModules(sourcePane);
			
			// add it to the database
			// OriginalModuleID to have it work with shortcut module
			ModulesDB admin         =   new ModulesDB();
			admin.UpdateModuleOrder(OriginalModuleID, 99, targetPane);

			// reload the portalSettings from the database
			// CSU 8/4/08
			ADNPage.portalSettings.ReloadPortal(true);

			// reorder the modules in the source pane
			sourceList              =   GetModules(sourcePane);
			OrderModules(sourceList);

			// resave the order
			foreach (ModuleItem item in sourceList) 
				admin.UpdateModuleOrder(item.ID, item.Order, sourcePane);

			// reorder the modules in the target pane
			ArrayList targetList    =   GetModules(targetPane);
			OrderModules(targetList);

			// resave the order
			foreach (ModuleItem item in targetList) 
				admin.UpdateModuleOrder(item.ID, item.Order, targetPane);
			// Redirect to the same page to pick up changes
			RedirectToSamePage(true);
		}

		/// <summary>
		/// The UpDown_Click server event handler on this page is
		/// used to move a portal module up or down on a tab's layout pane
		/// </summary>
		private void UpDown_Click(Object sender, EventArgs e) 
		{
			int delta;

			//			string cmd = ((ModuleButton)sender).CommandName;
			//			string pane = ((ModuleButton)sender).CommandArgument;
			string cmd = ((ModuleButton)sender).Attributes["direction"];
			string pane = ((ModuleButton)sender).Attributes["pane"];

				
			ArrayList modules = GetModules(pane);

			// Determine the delta to apply in the order number for the module
			// within the list.  +3 moves down one item; -3 moves up one item
			if (cmd == "down") 
				delta = 3;
			else 
				delta = -3;

			foreach (ModuleItem item in modules)
			{
				if (item.ID == ModuleID)
					item.Order += delta;
			}

			// reorder the modules in the content pane
			OrderModules(modules);

			// resave the order
			ModulesDB admin = new ModulesDB();
			foreach (ModuleItem item in modules) 
				admin.UpdateModuleOrder(item.ID, item.Order, pane);
			// Redirect to the same page to pick up changes
			RedirectToSamePage(true);
		}
		#endregion Arrow button functions

		#region Delete Module functions
		/// <summary>
		/// The DeleteModuleButton_Click server event handler on this page is
		/// used to delete a portal module
		/// </summary>
		private void DeleteModuleButton_Click(Object sender, EventArgs e) 
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DeleteModuleButton_Click BEG moduleid: {0}.",ModuleID),ModuleTraceSwitch.Sw.Info);
			ModulesDB admin = new ModulesDB();
			admin.DeleteModule(ModuleID,GuidID);
			// Redirect to the same page to pick up changes
			RedirectToSamePage(false);
		}

		#endregion Delete Module functions

		#region Culture
		
		/// <summary>
		/// The module culture. If specified module should be showed
		/// only if current culture matches this setting.
		/// Colon separated list
		/// </summary>
		public virtual string Cultures
		{
			get
			{
				if (HttpContext.Current != null && Settings.ContainsKey(StStr.ModuleSettingsCulture))
					return Settings[StStr.ModuleSettingsCulture].ToString().Trim(new char[]{';'});
				return System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
			}
		}
		#endregion

		#region Content
		private object _content = null;

		/// <summary>
		/// Will return module content as an object, if called.
		/// </summary>
		public object Content
		{
			get
			{
				if ( _content == null )
				{
					_content = GetContent();
				}
				return _content;
			}
			set
			{
				_content = value;
			}
		}

		/// <summary>
		/// Used by Content to fetch module content, by raising Init and Load events on the module.
		/// </summary>
		public virtual object GetContent()
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl GetContent moduleid: {0}.",ModuleID),ModuleTraceSwitch.Sw.Info);
			StringBuilder sb    =   new  StringBuilder();
			StringWriter sw     =   new StringWriter(sb);
			HtmlTextWriter wr   =   new HtmlTextWriter(sw);
			string result       =   string.Empty;
			try
			{
				OnInit(EventArgs.Empty);
				OnLoad(EventArgs.Empty);
				Render(wr);
				wr.Flush();
				sw.Flush();
				result = sb.ToString();
			}
			catch (Exception ex)
			{
				if (ModuleTraceSwitch.Sw.TraceError)
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl GetContent ex: {0}", ex), ModuleTraceSwitch.Sw.Info);
			}
			finally
			{
				sw.Close();
				wr.Close();
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl GetContent result: {0}.",result),ModuleTraceSwitch.Sw.Info);
			return result;
		}
		#endregion Content
		
		#region Module UI Sizing
		
		protected string ModuleContainerID      =   string.Empty;
		protected string ModuleContainerTag     =   "div";
		/// <summary>
		/// Returns a module content sizing container tag with properties
		/// </summary>
		/// <paramref name="isBeginTag">Specifies whether to output the container's begin(true) or end(false) tag.</paramref>
		/// <returns>The literal control containing this tag</returns>
		private LiteralControl BuildModuleContentContainer(bool isBeginTag)
		{
			LiteralControl modContainer =   new LiteralControl();
			Unit width                  =   Settings.ContainsKey(StStr.ModuleSettingsContentWidth) ? 
													Settings[StStr.ModuleSettingsContentWidth].ToUnit() : Unit.Empty;
			Unit height                 =   Settings.ContainsKey(StStr.ModuleSettingsContentHeight) ? 
													Settings[StStr.ModuleSettingsContentHeight].ToUnit() : Unit.Empty;
			bool widthIsEmpty           =   (width == Unit.Empty) || (width.Value == 0) || width.IsEmpty;
			bool widthIsPurcentage      =   (width.Type == UnitType.Percentage);
			bool heightIsEmpty          =   (height == Unit.Empty) || (height.Value == 0) || height.IsEmpty;
			bool heightIsPurcentage     =   (height.Type == UnitType.Percentage);
			bool scrolling              =   Settings.ContainsKey(StStr.ModuleSettingsContentScrolling) ? 
													Settings[StStr.ModuleSettingsContentScrolling].ToBool() : false;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl BuildModuleContentContainer BEG isBeginTag:{0}, width:{1}, height:{2}, scrolling: {3}",new object[]{ isBeginTag, width, height,scrolling}),ModuleTraceSwitch.Sw.Info);
			if (isBeginTag)
			{
				StringBuilder sb        =   new StringBuilder();
				ModuleContainerID       =   string.Format("modcont_{0}",ClientID);
				string defaultClass     =   ModuleCssClass;
				string defaultStyle     =   ModuleCssStyle;
				// Add a class based on modulecss_Theme
				if ( string.IsNullOrEmpty(defaultStyle) )
				{
					const string mfmt1  =   "<{0} class='modulecss_{1} {3}' id='{2}' style='position: {4}; ";   // warning NO quote on last param!
					sb.AppendFormat(mfmt1,
						new object[] { ModuleContainerTag,CurrentModulesLayout.Name,ModuleContainerID,ModuleCssClass,ModuleDefaultCssPosition });
				}
				else
				{
					const string mfmt1  =   "<{0} class='modulecss_{1} {3}' id='{2}' style='{4}; ";   // warning NO quote on last param!
					sb.AppendFormat(mfmt1,
						new object[]{ModuleContainerTag,CurrentModulesLayout.Name,ModuleContainerID,ModuleCssClass,defaultStyle});
				}
				const string mfmt3      =   "width:{0}; ";   
				if (!widthIsEmpty)
					sb.AppendFormat(mfmt3,width);
				const string mfmt4      =   "height:{0}; ";
				if ( !heightIsEmpty )
					sb.AppendFormat(mfmt4,height);
				if ( string.IsNullOrEmpty(defaultStyle) )
				{
					const string mfmt5  =   "overflow: auto; ";
					const string mfmt5b =   "overflow: {0}; ";
					if ( scrolling )
						sb.Append(mfmt5);
					else if ( ModuleDefaulUseOverflow )
						sb.AppendFormat(mfmt5b,ModuleDefaultCssOverflow);
				}
				sb.Append("'>");
				modContainer.Text       = sb.ToString();
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl BuildModuleContentContainer modContainer.Text: {0}",modContainer.Text),ModuleTraceSwitch.Sw.Info);
			}
			else 
			{
				HttpBrowserCapabilities bCaps   =   Page.Request.Browser;
				Version v                       =   bCaps.EcmaScriptVersion;
				bool shouldGenerateScript       =   ( v.Major >= 1 ) && 
						(  (!widthIsEmpty && !widthIsPurcentage  && !heightIsEmpty && !heightIsPurcentage )
						  ||
						  ( scrolling && 
						  (( !widthIsEmpty && !widthIsPurcentage  ) || ( !heightIsEmpty && !heightIsPurcentage ) ) ));  
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl BuildModuleContentContainer v.Major:{0}, shouldGenerateScript: {1}",v.Major,shouldGenerateScript),ModuleTraceSwitch.Sw.Info);
				if ( shouldGenerateScript )
				{
					Type tp	                =	GetType();
					string pth              =   Path2.ToAbsolute(Config.PortalScriptsPath+"/autoResizeModule.js");
					const string src2       =   "if (document._portalmodules) document._portalmodules.GetModules(_xportalModules); document._portalmodules.ProcessAll();";
					// Register a client side script that will properly resize the content area of the module
					// to compensate for different height and width settings, as well as, the browser's tendency
					// to stretch the middle module width even when a specific width setting is specified.
					ADNPage.RegisterADNClientScriptInclude(this,tp, "autoSizeModules", pth);
					ADNPage.RegisterADNStartupScript(this,tp, "initAutoSizeModules", src2, true);
					ADNPage.RegisterADNArrayDeclaration(this,"_xportalModules", "'modcont_" + ClientID + "'");
				}
				modContainer.Text = string.Format("</{0}>\r",ModuleContainerTag);
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl BuildModuleContentContainer END isBeginTag:{0}",isBeginTag),ModuleTraceSwitch.Sw.Info);
			return modContainer;
		}

		// To support module width stretching/shrinking capability
		/// <summary>
		/// Updates the moduleControl literal control with proper width settings to render the 'module width stretching' option
		/// </summary>
		/// <paramref name="moduleControl">The literal control element to parse and modify.</paramref>
		/// <paramref name="isBeginTag">Specifies whether the moduleElement parameter is for the element's begin(true) or end(false) tag.</paramref>
		private void ProcessModuleStrecthing(Control moduleControl, bool isBeginTag)
		{
			if ( moduleControl == null || !(moduleControl is LiteralControl) )
				return;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ProcessModuleStrecthing BEG ModuleID: {0}, isBeginTag: {1}", ModuleID, isBeginTag),ModuleTraceSwitch.Sw.Info);
			LiteralControl moduleElement    =   (LiteralControl) moduleControl;
			bool isStretching               =   Settings[StStr.ModuleSettingsWidthStretching].ToBool();
			string tmp                      =   (moduleElement.Text != null) ? moduleElement.Text.Trim():string.Empty;
			//Need to remove the current width setting of the main table in the module Start(Title/NoTitle)Content section of the layout,
			//if this is to be a stretched module then insert a width attribute into it,
			//if not, then surround this table with another table that has an empty cell after the cell that contains the module's HTML,
			//in order to use up any space in the window that the module has not been defined for. (TBC)
			//if no width specified for module then the module will be at least 50% width of area remaining, or expand to hold its contents.
			if ( isBeginTag )
			{
				Regex r                     =   new Regex("<table[^>]*>");
				MatchCollection mc          =   r.Matches(tmp.ToLower(CultureInfo.InvariantCulture));
				//Only concerned with first match
				if ( mc.Count > 0 )
				{
					string TbMatch          =   mc[0].Value;
					int TIndx               =   mc[0].Index; 
					//find a width attribute in this match(if exists remove it)
					const string mfmt6      =   "width=((['\"][^'\"]*['\"])|([0-9]+))";
					Regex r1                =   new Regex(mfmt6);
					mc                      =   r1.Matches(TbMatch);
					if ( mc.Count > 0 )
					{
						int WIndx           =   mc[0].Index; 
						int WLength         =   mc[0].Value.Length;
						// remove the width attribut: stretching or not
						tmp                 =   tmp.Substring(0,WIndx+TIndx)+tmp.Substring(WIndx+TIndx+WLength);
						// first table tag element
						TbMatch             =   TbMatch.Substring(0,WIndx)+TbMatch.Substring(WIndx+WLength);
						if ( ModuleTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ProcessModuleStrecthing removed width: {0}", TbMatch),ModuleTraceSwitch.Sw.Info);
					}
					//find a style attribute in this match(if exists)
					const string mfmt7      =   "style=['\"][^'\"]*['\"]";
					Regex r2                =   new Regex(mfmt7);
					mc                      =   r2.Matches(TbMatch);
					if ( mc.Count > 0 )
					{
						// style index in table
						int SIndx           =   mc[0].Index;
						string strStyle     =   mc[0].Value;
						int SLength         =   strStyle.Length;
						//Next find a width style property(if exists) and modify it
						const string mfmt8  =   "width:[^;'\"]+[;'\"]";
						Regex r3            =   new Regex(mfmt8);
						mc                  =   r3.Matches(strStyle);
						if ( mc.Count > 0 )
						{
							// we must skip any border-width or similars
							int z           =   0;
							while (z < mc.Count)
							{
								int SwIndx  =    mc[z].Index;
								int SwLength=   mc[z].Value.Length - 1;
								if (SwIndx > 0 && strStyle[SwIndx - 1] == '-')
								{
									z++;
									continue;
								}
								if (isStretching) // replace style width by 100% to stretch
								{
									tmp     =   tmp.Substring(0, SIndx + SwIndx + TIndx) + "width:100%" + tmp.Substring(SIndx + SwIndx + TIndx + SwLength);
									if (ModuleTraceSwitch.Sw.TraceVerbose)
										Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ProcessModuleStrecthing isStretching -> style changed with 'width:100%' :{0}", mc[z].Value), ModuleTraceSwitch.Sw.Info);
								}
								else // remove any width ???????
								{
									tmp     =   tmp.Substring(0, SIndx + SwIndx + TIndx) + tmp.Substring(SIndx + SwIndx + TIndx + SwLength);
									if (ModuleTraceSwitch.Sw.TraceVerbose)
										Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ProcessModuleStrecthing !isStretching -> removing any with :{0}", mc[z].Value), ModuleTraceSwitch.Sw.Info);
								}
								break;
							}
						}
						// a style is here, add width style property to the existing style attribute
						else if (isStretching)
						{
							tmp             =   tmp.Substring(0, SIndx + TIndx + 7) + "width:100%;" + tmp.Substring(SIndx + TIndx + 7);
							if (ModuleTraceSwitch.Sw.TraceVerbose)
								Trace2.WriteLine("[V]PortalModuleControl ProcessModuleStrecthing isStretching -> added to style 'width:100%;'", ModuleTraceSwitch.Sw.Info);
						}
					}
					// no style present, add width style property to a new style attribute if stretching
					else if (isStretching)
					{
						tmp                 =   tmp.Substring(0, TIndx + 7) + "style='width:100%;' " + tmp.Substring(TIndx + 7);
						if (ModuleTraceSwitch.Sw.TraceVerbose)
							Trace2.WriteLine("[V]PortalModuleControl ProcessModuleStrecthing isStretching -> no style, added style 'style='width:100%'", ModuleTraceSwitch.Sw.Info);
					}
				}
				// here we wrap everything in another table
				if (!isStretching)
				{
					const string mfmt9      =   "<table cellpadding='0' cellspacing='0' border='0'><tbody><tr>\n<td>";
					tmp                     =   mfmt9 + tmp;
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine("[V]PortalModuleControl ProcessModuleStrecthing !isStretching -> wrapping module in another table with one row one column.", ModuleTraceSwitch.Sw.Info);
				}
			}
			// we close the wrap table added on first pass
			else if (!isStretching)
			{
				const string mfmt10         =  "</td><td></td>\n</tr></tbody></table>";
				tmp                         +=  mfmt10;
				if (ModuleTraceSwitch.Sw.TraceVerbose)
					Trace2.WriteLine("[V]PortalModuleControl ProcessModuleStrecthing !isStretching -> closing the added table.", ModuleTraceSwitch.Sw.Info);
			}
			moduleElement.Text              =   tmp;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ProcessModuleStrecthing END ModuleID: {0}, isBeginTag: {1}", ModuleID, isBeginTag),ModuleTraceSwitch.Sw.Info);
		}
		#endregion Module UI Sizing

		#region ModulesLayout

		/// <summary>
		/// Before apply layout ADNPageModule designer checks this property to be true.
		/// On inherited modules you can override this property to not apply layout on specific controls.
		/// </summary>
		public virtual bool ApplyLayout
		{
			get
			{
				return Settings[StStr.ModuleSettingsApplyModuleLayout].ToBool();
			}
		}

		/// <summary>
		/// Don't apply layout skin when no header
		/// </summary>
		public virtual bool LayoutNoSkin
		{
			get
			{
				return Settings[StStr.ModuleSettingsApplyLayoutNoSkin].ToBool();
			}
		}

		string _LayoutType = string.Empty;
		public string LayoutType
		{
			get
			{
				if (_LayoutType == string.Empty)
				{
					_LayoutType = StStr.DefaultModulesLayout;
					if ( Settings[StStr.ModuleSettingsModuleLayout].ToInt() == (int)ModuleLayoutOption.Alt)
						_LayoutType = StStr.AltModulesLayout;
				}
				return _LayoutType;
			}
		}

		/// <summary>
		/// Layout used to bild this module
		/// Its name is in the Name property
		/// </summary>
		public ModulesLayout CurrentModulesLayout
		{
			get
			{
				return _CurrentModulesLayout;
			}
		}



		/// <summary>
		/// Sets the CurrentModulesLayout - allowing custom ModulesLayout per module
		/// We use only the old module layout system because .NET2 themes are only allowed on page detail, and not on modules
		/// </summary>
		protected virtual void SetupLayout()
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl SetupLayout BEG PageID: {0}, ModuleID: {1}", PageID, ModuleID),ModuleTraceSwitch.Sw.Info);
			if (portalSettings.AllowCustomModulesLayout )
			{
				// substitute custom layout for this module
				ModulesLayoutManager _tm    =   new ModulesLayoutManager(portalSettings.PortalPath);
				string       strTm          =   string.Empty;
				string strMPageFile         =   string.Empty;

				try
				{
					if (Settings.StringValue(StStr.ModuleSettingsModuleModuleLayout, ref strTm))
					{
						if ( ModuleTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl SetupLayout Loading ModuleID: {0}, custom ModulesLayout: [{1}]", ModuleID, strTm),ModuleTraceSwitch.Sw.Info);
						_tm.Load(strTm);
						_CurrentModulesLayout =     _tm.CurrentModulesLayout;
					}
				}
				catch (Exception ex)
				{
					if ( ModuleTraceSwitch.Sw.TraceError )
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl SetupLayout Failed to load custom moduleLayout: {0}, ModuleID: {1}, ex: {2} ", strTm, ModuleID, ex),ModuleTraceSwitch.Sw.Info);
					_CurrentModulesLayout   =   portalSettings.GetCurrentModulesLayout(LayoutType);
				}
			}
			if ( CurrentModulesLayout == null )
			{
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl SetupLayout ModuleID: {0}, taking portal moduleLayout Type: [{1}]", ModuleID, LayoutType),ModuleTraceSwitch.Sw.Info);
				_CurrentModulesLayout       =   portalSettings.GetCurrentModulesLayout(LayoutType);
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl SetupLayout END ModuleID: {0}, Type: {1},ModulesLayout: [{2}]", 
					new object[] { ModuleID, LayoutType, CurrentModulesLayout.Name}),ModuleTraceSwitch.Sw.Info);
		}
		#endregion ModulesLayout

		#region Extended LAyout

		public bool UseExternalDiv
		{
			get
			{
				return Settings[StStr.ModuleSettingsUseInnerDiv].ToBool();
			}
		}

		public string ExternalCssClass
		{
			get
			{
				return Settings[StStr.ModuleSettingsExtCssClass].ToString().Replace(",",string.Empty).Replace("'",string.Empty);
			}
		}

		public string ExternalCssStyle
		{
			get
			{
				return Settings[StStr.ModuleSettingsExtStyle].ToString().Replace(",",string.Empty).Replace("'",string.Empty);
			}
		}

		public string ModuleCssClass
		{
			get
			{
				return Settings[StStr.ModuleSettingsCssClass].ToString().Replace(",",string.Empty).Replace("'",string.Empty);
			}
		}

		public string ModuleCssStyle
		{
			get
			{
				return Settings[StStr.ModuleSettingsStyle].ToString().Replace(",",string.Empty).Replace("'",string.Empty);
			}
		}

		public string ModuleDefaultCssPosition
		{
			get
			{
				return Settings[StStr.ModuleSettingsDefaultCssPosition].ToString().Replace(",",string.Empty).Replace("'",string.Empty);
			}
		}

		public bool ModuleDefaulUseOverflow
		{
			get
			{
				return Settings[StStr.ModuleSettingsUseOverflow].ToBool();
			}
		}

		public string ModuleDefaultCssOverflow
		{
			get
			{
				return Settings[StStr.ModuleSettingsDefaultCssOverflow].ToString().Replace(",",string.Empty).Replace("'",string.Empty);
			}
		}
			
		#endregion

		#region Rendering

		/// <summary>
		/// used to hold the consolidated list of buttons for the module
		/// </summary>
		private ArrayList ButtonList        =   new ArrayList(6);
		/// <summary>
		/// User Buttons
		/// </summary>
		public ArrayList ButtonListUser     =   new ArrayList(3);
		/// <summary>
		/// Admin Buttons
		/// </summary>
		public ArrayList ButtonListAdmLeft  =  new ArrayList(3);
		public ArrayList ButtonListAdmRight =  new ArrayList(3);
		/// <summary>
		/// Custom Buttons
		/// </summary>
		public ArrayList ButtonListCustom   =   new ArrayList(3);

		// switches used for building module hierarchy
		bool _buildTitle	                =   true;
		bool _buildButtons	                =   true;
		bool _buildBody		                =   true;

		/// <summary>
		/// Merges the three public button lists into one.
		/// </summary>
		protected virtual void MergeButtonLists()
		{
			Image ImgDivider        =   new Image();
			ImgDivider.SkinID       =   "Spacer";

			ImgDivider.CssClass = (LayoutType == StStr.DefaultModulesLayout ) ? "ModuleSpacer":"ModuleSpacerAlt";

			// merge the button lists
			if ( ButtonListAdmLeft.Count > 0 )
				ButtonListAdmLeft.Add(ImgDivider);
			if (ButtonListUser.Count > 0 && (ButtonListCustom.Count > 0 || ButtonListAdmRight.Count > 0))
				ButtonListUser.Add(ImgDivider);
			if (ButtonListCustom.Count > 0 && ButtonListAdmRight.Count > 0)
				ButtonListAdmRight.Add(ImgDivider);
			foreach (Control btn in ButtonListAdmLeft)
				ButtonList.Add(btn);
			foreach (Control btn in ButtonListUser)
				ButtonList.Add(btn);
			foreach (Control btn in ButtonListAdmRight)
				ButtonList.Add(btn);
			foreach (Control btn in ButtonListCustom)
				ButtonList.Add(btn);
		}

		/// <summary>
		/// Builds the three public button lists
		/// </summary>
		protected virtual void BuildButtonLists()
		{
			// user buttons
			if ( BackButton != null ) 
				ButtonListUser.Add(BackButton);
			//if ( this.PrintButton != null )	this.ButtonListUser.Add(this.PrintButton);
			if ( HelpButton != null ) 
				ButtonListUser.Add(HelpButton);
			if (AddButton != null)
				ButtonListUser.Add(AddButton);
			if (EditButton != null)
				ButtonListUser.Add(EditButton);

			// admin left buttons
			if (LeftButton != null)
				ButtonListAdmLeft.Add(LeftButton);
			if ( UpButton != null )
				ButtonListAdmLeft.Add(UpButton);

			// admin right buttons
			if ( DeleteModuleButton != null ) 
				ButtonListAdmRight.Add(DeleteModuleButton);
			if ( PropertiesButton != null ) 
				ButtonListAdmRight.Add(PropertiesButton);
			if ( SecurityButton != null ) 
				ButtonListAdmRight.Add(SecurityButton);
			if ( DownButton != null )
				ButtonListAdmRight.Add(DownButton);
			if ( RightButton != null )
				ButtonListAdmRight.Add(RightButton);

			// custom buttons
			if ( MinMaxButton != null )
				ButtonListCustom.Add(MinMaxButton);
			if ( CloseButton != null )
				ButtonListCustom.Add(CloseButton);
		}

		/// <summary>
		/// Makes the decisions about what needs to be built and calls the appropriate methods
		/// </summary>
		protected virtual void BuildControlHierarchy()
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl BuildControlHierarchy BEG Build SupportCollapsable: {0}, ShowTitle: {1}, ButtonList.Count: {2}", SupportCollapsable, ShowTitle, ButtonList.Count),ModuleTraceSwitch.Sw.Info);
			if ( SupportCollapsable && AddonNice.BLL.UserConfig.UserDesktop.isMinimized(ModuleID) )
				_buildBody      =   false;
			else if ( !ShowTitle )
				_buildTitle     =   false;
			if ( ButtonList.Count == 0 )
				_buildButtons   =   false;

			if ( ModuleID != OriginalModuleID )
					BuildShortcut();
			else if ( !ApplyLayout )
					BuildNoLayout();
			else    Build();
			// wrap the module in a div with the ModuleID and Module type name as class name + a second class name witch include CurrentModulesLayout Name- useful for CSS styling 
			if ( UseExternalDiv )
			{
				string extrstyle    =   ExternalCssStyle;
				string divstr       =   string.Empty;
				if ( string.IsNullOrEmpty(extrstyle) )
					divstr  =   string.Format("<div id=\"mID{0}\" class=\"{1} {1}_{2} {3}\">",
						new object[]{ModuleID,GetType().BaseType.Name,CurrentModulesLayout.Name, ExternalCssClass});
				else
					divstr  =   string.Format("<div id='mID{0}' class='{1} {1}_{2} {3}' style='{4}' >",
						new object[]{ModuleID,GetType().BaseType.Name,CurrentModulesLayout.Name, ExternalCssClass,extrstyle});
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl BuildControlHierarchy external div: [{0}].",divstr),ModuleTraceSwitch.Sw.Info);
				_header.Controls.AddAt(0,new LiteralControl(divstr));
				_footer.Controls.Add(new LiteralControl("</div>"));
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]PortalModuleControl BuildControlHierarchy END.",ModuleTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Special build when the module is shortcut module
		/// </summary>f
		protected virtual void BuildShortcut()
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]PortalModuleControl BuildShortcut",ModuleTraceSwitch.Sw.Info);
			// do nothing - just passes the target contents through. The layout will be applied
			// to the containing shortcut module.
		}

		/// <summary>
		/// Method builds "no Layout" version of module.
		/// </summary>
		protected virtual void BuildNoLayout()
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]PortalModuleControl BuildNoLayout BEG.",ModuleTraceSwitch.Sw.Info);
			Table t         =   new Table();
			t.Style.Add(HtmlTextWriterStyle.Width,"100%");
			t.CssClass      =   "TableNoLayout";
			TableRow tr     =   new TableRow();
			t.Controls.Add(tr);
			TableCell tc;
			
			if ( _buildTitle )
			{
				tc          =   new TableCell();
				if (!_buildButtons)
				{
					tc.Style.Add(HtmlTextWriterStyle.Width,"100%");
				}
				else
				{
					tc.Style.Add(HtmlTextWriterStyle.Width,"60%");
				}
				tc.CssClass     =   "TitleNoLayout";
				tc.Controls.Add(new LiteralControl(TitleText));
				tr.Controls.Add(tc);
			}

			if ( _buildButtons )
			{
				// we keep buttons on the right
				if ( !_buildTitle )
				{
					tc          =   new TableCell();
					tc.Style.Add(HtmlTextWriterStyle.Width,"100%");
				}
				else 
				{
					tc              =   new TableCell();
					tc.Style.Add(HtmlTextWriterStyle.Width,"40%");
				}
				tc.CssClass     =   "ButtonsNoLayout";
				foreach( Control _button in ButtonList)
				{
					tc.Controls.Add(_button); //Add Button
				}
				tr.Controls.Add(tc);
			}

			if ( _buildTitle || _buildButtons )
				_header.Controls.Add(t);

			if ( !_buildBody )
			{
				for ( int i = 1 ; i < Controls.Count ; i++ )
					Controls[i].Visible = false;
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]PortalModuleControl BuildNoLayout END.",ModuleTraceSwitch.Sw.Info);
		}

		#region layout webparts accessors

		LiteralControl _TitleBeforeButton   =   null;
		protected LiteralControl TitleBeforeButton
		{
			get
			{
				if ( _TitleBeforeButton == null )
					_TitleBeforeButton  =   CurrentModulesLayout.GetLiteralControl("TitleBeforeButton");
				return _TitleBeforeButton;
			}
			set
			{
				_TitleBeforeButton  =   value;
			}
		}

		LiteralControl _TitleAfterButton   =   null;
		protected LiteralControl TitleAfterButton
		{
			get
			{
				if ( _TitleAfterButton == null )
					_TitleAfterButton  =   CurrentModulesLayout.GetLiteralControl("TitleAfterButton");
				return _TitleAfterButton;
			}
			set
			{
				_TitleAfterButton  =   value;
			}
		}

		LiteralControl _ControlNoTitleStart   =   null;
		protected LiteralControl ControlNoTitleStart
		{
			get
			{
				if ( _ControlNoTitleStart == null )
					_ControlNoTitleStart  =   CurrentModulesLayout.GetLiteralControl("ControlNoTitleStart");
				return _ControlNoTitleStart;
			}
			set
			{
				_ControlNoTitleStart  =   value;
			}
		}

		LiteralControl _ControlTitleStart   =   null;
		protected LiteralControl ControlTitleStart
		{
			get
			{
				if ( _ControlTitleStart == null )
					_ControlTitleStart  =   CurrentModulesLayout.GetLiteralControl("ControlTitleStart");
				return _ControlTitleStart;
			}
			set
			{
				_ControlTitleStart  =   value;
			}
		}

		LiteralControl _TitleStart   =   null;
		protected LiteralControl TitleStart
		{
			get
			{
				if ( _TitleStart == null )
					_TitleStart  =   CurrentModulesLayout.GetLiteralControl("TitleStart");
				return _TitleStart;
			}
			set
			{
				_TitleStart  =   value;
			}
		}
			
		LiteralControl _TitleMiddle   =   null;
		protected LiteralControl TitleMiddle
		{
			get
			{
				if ( _TitleMiddle == null )
					_TitleMiddle  =   CurrentModulesLayout.GetLiteralControl("TitleMiddle");
				return _TitleMiddle;
			}
			set
			{
				_TitleMiddle  =   value;
			}
		}

		LiteralControl _ControlNoTitleEnd   =   null;
		protected LiteralControl ControlNoTitleEnd
		{
			get
			{
				if ( _ControlNoTitleEnd == null )
					_ControlNoTitleEnd  =   CurrentModulesLayout.GetLiteralControl("ControlNoTitleEnd");
				return _ControlNoTitleEnd;
			}
			set
			{
				_ControlNoTitleEnd  =   value;
			}
		}
		
		LiteralControl _ControlTitleBeforeControl   =   null;
		protected LiteralControl ControlTitleBeforeControl
		{
			get
			{
				if ( _ControlTitleBeforeControl == null )
					_ControlTitleBeforeControl  =   CurrentModulesLayout.GetLiteralControl("ControlTitleBeforeControl");
				return _ControlTitleBeforeControl;
			}
			set
			{
				_ControlTitleBeforeControl  =   value;
			}
		}

		LiteralControl _ControlTitleAfterControl   =   null;
		protected LiteralControl ControlTitleAfterControl
		{
			get
			{
				if ( _ControlTitleAfterControl == null )
					_ControlTitleAfterControl  =   CurrentModulesLayout.GetLiteralControl("ControlTitleAfterControl");
				return _ControlTitleAfterControl;
			}
			set
			{
				_ControlTitleAfterControl  =   value;
			}
		}

		LiteralControl _ControlTitleEnd   =   null;
		protected LiteralControl ControlTitleEnd
		{
			get
			{
				if ( _ControlTitleEnd == null )
					_ControlTitleEnd  =   CurrentModulesLayout.GetLiteralControl("ControlTitleEnd");
				return _ControlTitleEnd;
			}
			set
			{
				_ControlTitleEnd  =   value;
			}
		}

		LiteralControl _TitleEnd   =   null;
		protected LiteralControl TitleEnd
		{
			get
			{
				if ( _TitleEnd == null )
					_TitleEnd  =   CurrentModulesLayout.GetLiteralControl("TitleEnd");
				return _TitleEnd;
			}
			set
			{
				_TitleEnd  =   value;
			}
		}

		#endregion layout webparts accessors

		
		/// <summary>
		/// Builds the "with layout" versions of the module, with optional Title, Buttons and Body.
		/// </summary>
		protected virtual void Build()
		{
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Build BEG _buildTitle:{0}, _buildButtons:{1}, _buildBody:{2}", _buildTitle, _buildButtons, _buildBody),ModuleTraceSwitch.Sw.Info);
			if ( !_buildTitle && !_buildButtons &&  LayoutNoSkin )
				_header.Controls.Add(ControlNoTitleStart);
			else 
			{
				_header.Controls.Add(ControlTitleStart);
				_header.Controls.Add(TitleStart);
			
				if ( _buildTitle )
					_header.Controls.Add(new LiteralControl(TitleText));
				_header.Controls.Add(TitleMiddle);
				
				// No module buttons or ReadOnly
				if ( _buildButtons && !ReadOnly )
				{
					foreach ( Control _button in ButtonList )
					{
						_header.Controls.Add(TitleBeforeButton);
						_header.Controls.Add(_button);
						_header.Controls.Add(TitleAfterButton);
					}
				}
				_header.Controls.Add(TitleEnd);
			}

			if ( !_buildBody )
			{
				// starts at 1 to keep first placeholder already inserted
				for ( int i = 1 ; i < Controls.Count ; i++ )
					Controls[i].Visible = false;
			}

			// this must be the first footer control (besides custom ones )
			if ( _buildBody )
				_footer.Controls.Add(BuildModuleContentContainer(false));
			if ( !_buildTitle && !_buildButtons && LayoutNoSkin )
				_footer.Controls.Add(ControlNoTitleEnd);
			else 
			{
				_header.Controls.Add(ControlTitleBeforeControl);
				_footer.Controls.Add(ControlTitleAfterControl);
				_footer.Controls.Add(ControlTitleEnd);
			}

			// To support auto width sizing and scrollable module content
			// this must be the last header control
			if ( _buildBody )
				_header.Controls.Add(BuildModuleContentContainer(true));
			if ( _header.Controls.Count > 0 && _footer.Controls.Count > 0)
			{
				//Process the first header control as the module's outer most begin tag element
				ProcessModuleStrecthing(_header.Controls[0], true);
				//Process the last footer control as the module's outer most end tag element
				ProcessModuleStrecthing(_footer.Controls[_footer.Controls.Count-1], false);
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Build END _header.Controls.Count:{0}, _footer.Controls.Count:{1}", _header.Controls.Count, _footer.Controls.Count),ModuleTraceSwitch.Sw.Info);
		}

		#endregion Rendering

		#region Module Methods

		/// <summary>
		///  Transforms utc dates in local dates, warning it closes the datreader sent
		/// CS 9/04 Method to use with pagingdatagrids that are alimented by a DataReader
		/// the DataGrid must have CustomPaging and AllowPaging attributes set
		/// </summary>
		public static ICollection CreateDataSource(SqlDataReader dr,DataGrid Grid) 
		{
			return CreateDataSource(dr,Grid,true) ;
		}

		/// <summary>
		///  Transforms utc dates in local dates, beware: it closes the datareader sent
		/// Could also be used to use with paging datagrids that are alimented by a DataReader
		/// the DataGrid must have CustomPaging and AllowPaging attributes set
		/// </summary>
		public static ICollection CreateDataSource(SqlDataReader dr,DataGrid Grid,bool ShouldBind) 
		{
			if ( Grid == null )
			{
				if ( ModuleTraceSwitch.Sw.TraceError )
					Trace2.WriteLine( "[E]PortalModuleControl CreateDataSource grid null",ModuleTraceSwitch.Sw.Info);
				throw new ArgumentException("PortalModuleControl CreateDataSource grid null.");
			}
			DataView dv							=	null;
			try
			{
				int StartIdx					=	Grid.PageSize * Grid.CurrentPageIndex;
				int EndIdx						=	StartIdx + Grid.PageSize;
				dv								=	CreateDataView(dr,StartIdx,EndIdx);
				Grid.VirtualItemCount			=	dv.Count;
			}
			catch (Exception ex)
			{
				if ( ModuleTraceSwitch.Sw.TraceError )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl CreateDataSource 1 ex:{0}", ex),ModuleTraceSwitch.Sw.Info);
				throw;
			}
			Grid.DataSource					=	dv;
			if ( ShouldBind )
				Grid.DataBind();
			return dv;
		}

		/// <summary>
		///  Transforms utc dates in local dates, warning it closes the dataReader sent
		/// return a dataview based on a table created on the SqlDataReader 
		/// </summary>
		public static DataView CreateDataView(SqlDataReader dr)
		{
			return CreateDataView(dr, 0, int.MaxValue);
		}

		/// <summary>
		///  Transforms utc dates in local dates, warning it closes the dataReader sent
		/// return a dataview based on a table created on the SqlDataReader 
		/// </summary>
		public static DataView CreateDataView(SqlDataReader dr,int StartIdx,int EndIdx) 
		{
			DataTable Tb						=	new  DataTable();
			DateTime MinValue					=	DateTime.MinValue.Date.AddDays(10);
			DateTime MaxValue					=	DateTime.MaxValue.Date.AddDays(-10);
			try
			{
				// From the schema of the table, we create a table object
				DataTable dt					=	dr.GetSchemaTable();
				foreach (DataRow rw in dt.Rows)
				{
					string str					= (string)rw["ColumnName"];
					if (Tb.Columns[str] != null)
						continue;
					DataColumn c				= new DataColumn(str, (System.Type)rw["DataType"]);
					Tb.Columns.Add(c);
				}

				// Populate the table with sample values. When using custom paging,
				// a query should only return enough data to fill a single page, 
				// beginning at the start index.
				int i							= 0;
				while (dr.Read())
				{
					if (i >= StartIdx && i < EndIdx)
					{
						DataRow rw				= Tb.NewRow();
						for (int j = 0; j < dr.FieldCount; j++)
						{
							string nm = dr.GetName(j);
							try
							{
								object ob		= dr[nm];
								if (ob == null || ob == System.DBNull.Value)
									rw[nm]		= System.DBNull.Value;
								else
								{
									if (Tb.Columns[nm].DataType == typeof(DateTime))
									{
										DateTime wdt = (DateTime)ob;
										if (wdt >= MinValue && wdt <= MaxValue)
											rw[nm] = wdt.ToLocalTime();
										else rw[nm] = wdt;
									}
									else rw[nm] = ob;
								}
							}
							catch (Exception ex)
							{
								if ( ModuleTraceSwitch.Sw.TraceError )
									Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl CreateDataSource ColumnName : {0}, ex: {1}", nm, ex),ModuleTraceSwitch.Sw.Info);
								throw;
							}
						}
						Tb.Rows.Add(rw);
					}
					i++;
				}
			}
			catch (Exception ex)
			{
				if ( ModuleTraceSwitch.Sw.TraceError )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl CreateDataSource ex:{0}", ex),ModuleTraceSwitch.Sw.Info);
				throw;
			}
			finally
			{
				if (dr != null)
					dr.Close();
			}
			DataView dv							=	new DataView(Tb);
			return dv;
		}


		#endregion Module Methods

		#region Methods to override in child classes
		/// <summary>
		/// Called during Onload event to override for adding specific controls to the global tooltip manager
		/// </summary>
		protected virtual void AddTargetToGlobalToolTipManager()
		{
		}
		#endregion Methods to override in child classes
		
		#region Install / Uninstall Implementation

		/// <summary>
		/// Necessary to install modules: automatically called by installer after instanciation of an objet
		/// Search for an install.sql proc in the module folder, run it if not already run in this install process
		/// </summary>
		public virtual void Install(IDictionary stateSaver,bool backupCustomizations,bool publish)
		{
			string tpName               =   GetType().Name;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Install Module: '{0}', Guid: {1}", tpName, GuidID),ModuleTraceSwitch.Sw.Info);
			string currentScriptName	=   Server.MapPath(TemplateSourceDirectory + "/Install.sql");
			// Is this script already run in this install
			if (stateSaver.Contains(currentScriptName))
			{
				object ob               =   stateSaver[currentScriptName];
				if ((ob is bool) && ((bool)ob))
				{
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Install script: '{0}', already runned, jumping over.", currentScriptName),ModuleTraceSwitch.Sw.Info);
					return;
				}
			}
			if (File.Exists(currentScriptName))
			{
				DBHelper execScript     =   new AddonNice.Helpers.DBHelper();
				try
				{
					execScript.ExecuteScript(currentScriptName, true);
				}
				catch (Exception ex)
				{
					if (ModuleTraceSwitch.Sw.TraceError)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl Install ex: {0}",ex) , ModuleTraceSwitch.Sw.Info);
				}
				finally
				{
					ArrayList errors    =   execScript.errors;
					if (errors.Count > 0)
					{
						stateSaver[currentScriptName]   =   false;
						stateSaver["Errors"]            =   errors;
						string msg = string.Format("[E]PortalModuleControl Install error occurred: {0}", errors[0]);
						if (ModuleTraceSwitch.Sw.TraceError)
							Trace2.WriteLine(msg, ModuleTraceSwitch.Sw.Info);
						// will call rollback
						throw new Exception(msg);
					}
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Install Module: '{0}', success for script: {1}.", tpName, currentScriptName),ModuleTraceSwitch.Sw.Info);
				stateSaver[currentScriptName]   =   true;
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Install END Module: {0}, Guid: {1}", tpName, GuidID),ModuleTraceSwitch.Sw.Info);
		}

		
		/// <summary>
		/// Called when a module as already been installed, doing an upgrade
		/// Default is to do exactly same job as Install
		/// </summary>
		public virtual void ReInstall(IDictionary stateSaver, bool backupCustomizations,bool publish)
		{
			string tpName               =   GetType().Name;
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ReInstall Module: '{0}', Guid: {1}", tpName, GuidID),ModuleTraceSwitch.Sw.Info);
			string currentScriptName	=   Server.MapPath(TemplateSourceDirectory + "/Install.sql");
			// Is this script already run in this install
			if (stateSaver.Contains(currentScriptName))
			{
				object ob               =   stateSaver[currentScriptName];
				if ((ob is bool) && ((bool)ob))
				{
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Install script: '{0}', already runned, jumping over.", currentScriptName),ModuleTraceSwitch.Sw.Info);
					return;
				}
			}
			if (File.Exists(currentScriptName))
			{
				DBHelper execScript     =   new AddonNice.Helpers.DBHelper();
				try
				{
					execScript.ExecuteScript(currentScriptName, true);
				}
				catch (Exception ex)
				{
					if (ModuleTraceSwitch.Sw.TraceError)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl ReInstall ex: {0}",ex) , ModuleTraceSwitch.Sw.Info);
				}
				finally
				{
					ArrayList errors = execScript.errors;
					if (errors.Count > 0)
					{
						stateSaver[currentScriptName]   =   false;
						stateSaver["Errors"]            =   errors;
						string msg = string.Format("[E]PortalModuleControl ReInstall error occurred: {0}", errors[0]);
						if (ModuleTraceSwitch.Sw.TraceError)
							Trace2.WriteLine(msg, ModuleTraceSwitch.Sw.Info);
						// will call rollback
						throw new Exception(msg);
					}
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ReInstall Module: '{0}', success for script: {1}.", tpName, currentScriptName),ModuleTraceSwitch.Sw.Info);
				stateSaver[currentScriptName]   =   true;
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl ReInstall END Module: {0}, Guid: {1}", tpName, GuidID),ModuleTraceSwitch.Sw.Info);
		}

		
		/// <summary>
		/// Called as a final install phase to do some task such as adding module to a predefined page
		/// This method is not called when running an upgrade
		/// </summary>
		public virtual void PostInstall(IDictionary stateSaver,bool install,bool backupCustomizations,bool publish)
		{
			if (InstallTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl PostInstall called Module : {0}, Guid: {1}, Install: {2}.", 
					GetType().Name, GuidID,install), InstallTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Necessary to uninstall modules: automatically called by installer after instanciation of an objet
		/// Search for an Uninstall.sql proc in the module folder, run it if not already run in this install process
		/// </summary>
		public virtual void Uninstall(IDictionary stateSaver, bool backupCustomizations,bool publish)
		{
			string tpName               =   GetType().Name;
			//Cannot be uninstalled if admin module
			if (AdminModule)
			{
				string msg  =   string.Format("[V]PortalModuleControl Uninstalling forbidden for admin Module: {0}, Guid: {1}", tpName, GuidID);
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( msg,ModuleTraceSwitch.Sw.Info);
				throw new Exception(msg);
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Uninstall BEG Module: {0}, Guid: {1}", tpName, GuidID),ModuleTraceSwitch.Sw.Info);
			string currentScriptName	= Server.MapPath(this.TemplateSourceDirectory + "/Uninstall.sql");
			// Is this script already run in this install
			if (stateSaver.Contains(currentScriptName))
			{
				object ob = stateSaver[currentScriptName];
				if ((ob is bool) && ((bool)ob))
				{
					if ( ModuleTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl UnInstall script: '{0}', already runned, jumping over.", currentScriptName),ModuleTraceSwitch.Sw.Info);
					return;
				}
			}
			if (File.Exists(currentScriptName))
			{
				DBHelper execScript     =   new AddonNice.Helpers.DBHelper();
				try
				{
					execScript.ExecuteScript(currentScriptName, true);
				}
				catch (Exception ex)
				{
					if (ModuleTraceSwitch.Sw.TraceError)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl Install ex: {0}",ex) , ModuleTraceSwitch.Sw.Info);
				}
				finally
				{
					ArrayList errors = execScript.errors;
					if (errors.Count > 0)
					{
						string msg  =   string.Format("[E]PortalModuleControl Uninstall error occurred: {0}", errors[0]);
						if (ModuleTraceSwitch.Sw.TraceError)
							Trace2.WriteLine(msg, ModuleTraceSwitch.Sw.Info);
						// Call rollback
						throw new Exception(msg);
					}
				}
				if ( ModuleTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Uninstall Module: '{0}', success ofr script: {1}", tpName, currentScriptName),ModuleTraceSwitch.Sw.Info);
				stateSaver[currentScriptName]   =   true;
			}
			if ( ModuleTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl Uninstall END Module : {0}, Guid: {1}", GetType().Name, GuidID),ModuleTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Used for committing an installation 
		/// Default is to do nothing
		/// </summary>
		public virtual void Commit(System.Collections.IDictionary stateSaver)
		{
		}

		/// <summary>
		/// Used to rollback an installation
		/// Default is to do nothing
		/// </summary>
		public virtual void Rollback(System.Collections.IDictionary stateSaver)
		{
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Gets resources from assembly
		/// </summary>
		private string getResourceContent(string resourceID) 
		{
			Stream st = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceID);
			if (st != null)
			{
				StreamReader sr = new StreamReader(st);
				return sr.ReadToEnd();
			}
			return null;
		}
		#endregion

		#region Dock management
		const string pgCk   =   "AddonNice_DockCookie";
		
		protected virtual string DockWindowCookieName
		{
			get
			{
				return pgCk;
			}
		}
		/// <summary>
		/// To override when floating dock is used
		/// </summary>
		protected virtual RadDockLayout DockWindowLayout
		{
			get
			{
				return null;
			}
		}

		string DockWindowStates
		{
			get
			{
				string _dockStates;
				HttpCookie positionsCookie  =   Request.Cookies[DockWindowCookieName];
				if ( positionsCookie == null )
					_dockStates             =   string.Empty;
				else
					_dockStates             =   positionsCookie.Value;
				if (ModuleTraceSwitch.Sw.TraceVerbose)
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DockWindowStates _dockStates: '{0}'.",_dockStates),ModuleTraceSwitch.Sw.Info);
				return _dockStates;
			}
			set
			{
				HttpCookie positionsCookie  =   new HttpCookie(DockWindowCookieName, value);
				positionsCookie.Expires     =   DateTime.Now.AddYears(1);
				Response.Cookies.Add(positionsCookie);
			}
		}
	

		protected void DockWindowLayout_SaveDockLayout(object sender, DockLayoutEventArgs e)
		{
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DockWindowLayout_SaveDockLayout BEG DockWindowLayout null: {0}.",( DockWindowLayout == null )),ModuleTraceSwitch.Sw.Info);
			if ( DockWindowLayout == null )
				return;
			List<DockState> dockStates          =   DockWindowLayout.GetRegisteredDocksState();
			JavaScriptSerializer serializer     =   new JavaScriptSerializer();
			JavaScriptConverter[] converters    =   new JavaScriptConverter[1];
			converters[0]                       =   new DockStateJavaScriptUnitConverter();
			serializer.RegisterConverters(converters);

			StringBuilder sb                    =   new StringBuilder();
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DockWindowLayout_SaveDockLayout dockStates.Count: {0}.",dockStates.Count),ModuleTraceSwitch.Sw.Info);
			foreach(DockState state in dockStates)
			{
				InternalDockState mSt           =   new InternalDockState(state.Collapsed,state.DockZoneID,
															state.Index,state.Left,state.Top,state.UniqueName,state.Pinned,state.Width);
				string ser                      =   serializer.Serialize(mSt);
				sb.AppendFormat("{0}|",ser);
			}
			DockWindowStates                     =   sb.ToString();
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DockWindowLayout_SaveDockLayout END DockWindowStates: '{0}'.",DockWindowStates),ModuleTraceSwitch.Sw.Info);
		 }

		protected void DockWindowLayout_LoadDockLayout(object sender, DockLayoutEventArgs e)
		{
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DockWindowLayout_LoadDockLayout BEG DockWindowLayout null: {0}.",( DockWindowLayout == null )),ModuleTraceSwitch.Sw.Info);
			if ( DockWindowLayout == null )
				return;
			RadDock dock                        =   null;
			JavaScriptSerializer serializer     =   new JavaScriptSerializer();
			JavaScriptConverter[] converters    =   new JavaScriptConverter[1];
			converters[0]                       =   new DockStateJavaScriptUnitConverter();
			serializer.RegisterConverters(converters);
			try
			{
				string[] tStates                =   DockWindowStates.Split(new char[]{'|'}, StringSplitOptions.RemoveEmptyEntries);
				foreach (string str in tStates)
				{
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DockWindowLayout_LoadDockLayout serializer.Deserialize: '{0}'.",str),ModuleTraceSwitch.Sw.Info);
					InternalDockState mSt       =   serializer.Deserialize<InternalDockState>(str);
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DockWindowLayout_LoadDockLayout state: [{0}].",mSt),ModuleTraceSwitch.Sw.Info);
					dock                        =   (RadDock)DockWindowLayout.FindControl(mSt.UniqueName);
					DockState state             =   dock.GetState();
					if (ModuleTraceSwitch.Sw.TraceVerbose)
						Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalModuleControl DockWindowLayout_LoadDockLayout current state Collapsed: {0}, DockZoneID: '{1}', Index: {2}, Left: {3}, Top: {4}, UniqueName: '{5}', Pinned: {6}, Width: {7}.",
							new object[]{state.Collapsed,state.DockZoneID,state.Index,state.Left,state.Top,state.UniqueName,state.Pinned,state.Width}),ModuleTraceSwitch.Sw.Info);
					state.Collapsed             =   mSt.Collapsed;
					state.Left                  =   mSt.Left;
					state.Top                   =   mSt.Top;
					state.Width                 =   mSt.Width;
					state.Pinned                =   mSt.Pinned;
					dock.ApplyState(state);
				}
			}
			catch (Exception ex)
			{
				if (ModuleTraceSwitch.Sw.TraceError)
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PortalModuleControl DockWindowLayout_LoadDockLayout ex: {0}.",ex),ModuleTraceSwitch.Sw.Info);
				// bad cookie, remove content
				DockWindowStates                    =   string.Empty;
			}
			if (ModuleTraceSwitch.Sw.TraceVerbose)
				Trace2.WriteLine("[V]PortalModuleControl DockWindowLayout_LoadDockLayout END.",ModuleTraceSwitch.Sw.Info);
		}
		
		#endregion Dock management

		#region Methods for Date and query
		protected virtual DateTime QueryDate
		{
			get
			{
				if (!IsDesignMode)
					return ADNPage.QueryDate;
				return DateTime.Now;
			}
			set
			{
				if (!IsDesignMode)
				{
					ADNPage.QueryDate = value;
				}
			}
		}

		public virtual string SortOrder
		{
			get
			{
				if (!IsDesignMode)
					return ADNPage.SortOrder;
				return string.Empty;
			}
			set
			{
				if (!IsDesignMode)
					ADNPage.SortOrder = value;
			}
		}

		public virtual string SortDirection
		{
			get
			{
				if (!IsDesignMode)
					return ADNPage.SortDirection;
				return string.Empty;
			}
			set
			{
				if (!IsDesignMode)
					ADNPage.SortDirection = value;
			}
		}

		public virtual string Filter
		{
			get
			{
				if (!IsDesignMode)
					return ADNPage.Filter;
				return string.Empty;
			}
			set
			{
				if (!IsDesignMode)
					ADNPage.Filter = value;
			}
		}

		public virtual int PageSize
		{
			get
			{
				if (!IsDesignMode)
					return ADNPage.PageSize;
				return 0;
			}
			set
			{
				if (!IsDesignMode)
					ADNPage.PageSize = value;
			}
		}
		#endregion
	}
}
